Mar*_*bst 5 undefined typechecking typescript
下面的代码显然输入错误,但我不能在上面犯 TypeScript 错误。我打开了strict,strictNullChecks并且strictFunctionTypes很好地衡量了,但 TS 仍然坚定不移地相信这段代码很好而且很花哨。
abstract class A {
// You can pass an undefined to any A
public abstract foo(_x: number | undefined);
}
class B extends A {
// B is an A, but it prohibits passing in an undefined.
// Note that if we did `x: string`, TS would flag it as
// an error.
public foo(x: number) {
if (x === undefined) {
throw new Error("Type error!");
}
}
}
function makeAnA(): A {
// This typechecks correct, so B is clearly an A, in
// TS's opinion.
return new B();
}
function test() {
const b = makeAnA();
// b is a B, so this should not be possible
b.foo(undefined);
}
Run Code Online (Sandbox Code Playgroud)
这是预期的行为吗?有没有我可以打开的选项将其标记为错误?我不止一次被这个咬过。
这是一个设计决定。所有方法参数的行为都是双变量的。这意味着就 ts 而言,for 方法(_x: number) => void是 to 的子类型(_x: number | number) => void(反之亦然)。这显然是不妥当的。
最初,不仅方法参数具有双变行为,所有函数签名参数也具有双变行为。为了解决这个问题,strictFuctionTypes在 typescript 2.6 中添加了该标志。来自公关:
在这个 PR 中,我们引入了 --strictFunctionTypes 模式,在该模式中,函数类型参数位置以逆变方式而不是双变方式进行检查。更严格的检查适用于所有函数类型,除了源自方法或构造函数声明的函数类型。专门排除方法是为了确保泛型类和接口(例如 Array)继续大部分协变相关。严格检查方法的影响将是一个更大的破坏性变化,因为大量泛型类型将变得不变(即便如此,我们可能会继续探索这种更严格的模式)。
(已添加突出显示)
因此,在这里我们可以一睹让方法参数继续双变量关联的决定。是为了方便。如果没有这种不健全性,大多数类将是不变的。例如,如果Array是 不变的,Array<Dog>则不会是 的子类型Array<Animal>,从而在非常基本的代码中创建各种痛点。
虽然绝对不等价,但如果我们使用函数字段而不是方法(打开strictFunctionTypes),我们确实会收到一个错误:Type '(x: number) => void' is not assignable to type '(_x: number | undefined) => void'
abstract class A {
// You can pass an undefined to any A
public foo!: (_x: number | undefined) => void;
}
class B extends A {
// Error here
public foo: (x: number) => void = x => {
if (x === undefined) {
throw new Error("Type error!");
}
}
}
function makeAnA(): A {
//And here
return new B();
}
function test() {
const b = makeAnA();
// b is a B, so this should not be possible
b.foo(undefined);
}
Run Code Online (Sandbox Code Playgroud)
注意:上面的代码仅在没有它的情况下给出错误,strictFunctionTypes所有函数参数继续表现为双变量。
| 归档时间: |
|
| 查看次数: |
51 次 |
| 最近记录: |