TypeScript 在很多地方缺少只读修饰符,

ecr0jaav  于 7个月前  发布在  TypeScript
关注(0)|答案(4)|浏览(61)

lib 更新请求

我的代码中存在缺少只读修饰符的类型检查问题。例如,以下代码无法进行类型检查:

declare const vals: readonly number[]
Math.max.apply(null, vals)
                     ^^^^
                     Argument of type 'readonly number[]' is not
                     assignable to parameter of type 'number[]'

Playground 链接
这是由于以下签名导致的:

interface Math {
    max(...values: number[]): number
}

interface CallableFunction extends Function {
    apply<T, A extends any[], R>(this: (this: T, ...args: A) => R, thisArg: T, args: A): R
}

这些签名应该被替换为:

interface Math {
    max(...values: readonly number[]): number
}

interface CallableFunction extends Function {
    apply<T, A extends readonly any[], R>(this: (this: T, ...args: A) => R, thisArg: T, args: A): R
}

Playground 链接
基本上,每个数组剩余参数都应该是只读的,并且库中还有其他需要添加只读的地方。我已经在 fork 上进行了这些更改(请查看该分支的最后一次提交)。我不确定接下来该如何进行。有很多更改需要执行。也许这些更改应该分成几个部分进行?
请注意,如果 TypeScript 能够隐式地将数组剩余参数处理为只读(无论 readonly 修饰符是否存在),那么可以避免很多更改。我不认为有可变数组剩余参数的价值。然而,这会给类型检查器带来一个特殊情况,我个人并不特别喜欢这种情况。

vof42yt1

vof42yt11#

然而,这在类型检查器中添加了一个特殊情况,我个人并不特别喜欢这种做法。我不一定非要称之为“特殊情况”。剩余参数是一种语法构造,许多其他语法构造也会改变事物的类型。
实际上,这甚至可以做到保持变量的内部类型不变,但将函数的剩余参数用 Readonly Package 起来。例如:

function f(...args: number[]): void {
    args.push(10); // fine
}

f([1,2,3] as ReadonlyArray<number>); // fine as f actually has type (...readonly number[]) => void
von4xj4u

von4xj4u2#

我不认为需要重写任何休息参数(例如在 $x_{Math.max}$ 中)。最多,你需要将任何 捕获的 参数列表类型 $x_{A}$ 重写为 $x_{readonly [...A]}$,对吧?所以我们可以交换 $x_{args}$ 的类型。

$x_{

interface CallableFunction extends Function {
-    apply<T, A extends any[], R>(this: (this: T, ...args: A) => R, thisArg: T, args: A): R
+    apply<T, A extends any[], R>(this: (this: T, ...args: A) => R, thisArg: T, args: readonly [...A]): R
}

}$

laximzn5

laximzn53#

这是允许的:

declare const vals: readonly number[]
Math.max(...vals);

这很有道理,因为扩展数组总是会创建一个副本。所以问题仅限于 func.apply()

yx2lnoni

yx2lnoni4#

我认为没有必要重写任何休息参数(例如在 Math.max 中)。最多,你需要将任何 捕获的 参数列表类型 A 重写为 readonly [...A],对吗?所以我们可以切换 args

interface CallableFunction extends Function {
-    apply<T, A extends any[], R>(this: (this: T, ...args: A) => R, thisArg: T, args: A): R
+    apply<T, A extends any[], R>(this: (this: T, ...args: A) => R, thisArg: T, args: readonly [...A]): R
}

这绝对是一个更好的建议。

相关问题