gpt4 book ai didi

typescript - TypeScript 中 undefined 的协方差

转载 作者:行者123 更新时间:2023-12-03 16:48:06 24 4
gpt4 key购买 nike

下面的代码显然输入错误,但我不能在上面犯 TypeScript 错误。我打开了 strict ,以及 strictNullChecksstrictFunctionTypes很好的衡量标准,但 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);
}
这是预期的行为吗?有没有我可以打开的选项将其标记为错误?我不止一次被这个咬过。

最佳答案

这是一个设计决定。所有方法参数的行为都是双变的。这意味着就 ts 而言,对于方法 (_x: number) => void是 to (_x: number | number) => void 的子类型(反之亦然)。这显然是不妥当的。
最初不仅方法参数表现出双变,而且所有函数签名参数都表现出双变。为了解决这个问题,strictFuctionTypes标志是在 typescript 2.6 中添加的。来自 PR :

With this PR we introduce a --strictFunctionTypes mode in which function type parameter positions are checked contravariantly instead of bivariantly. The stricter checking applies to all function types, except those originating in method or constructor declarations. Methods are excluded specifically to ensure generic classes and interfaces (such as Array) continue to mostly relate covariantly. The impact of strictly checking methods would be a much bigger breaking change as a large number of generic types would become invariant (even so, we may continue to explore this stricter mode).

(highlight added)


因此,在这里我们可以一窥让方法参数继续双变量相关的决定。是为了方便。如果没有这种不健全,大多数类将是不变的。例如,如果 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);
}

Playground Link
备注 : 上面的代码只给出了 strictFunctionTypes 的错误因为没有它,所有函数参数都会继续双变。

关于typescript - TypeScript 中 undefined 的协方差,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63563424/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com