LGe*_*lis 7 typescript type-narrowing
考虑这个简单的片段。我也把它粘贴在这里:
type A =
| {
b: number;
}
| {
c: number;
};
function f1(a: A) {
if ('b' in a) {
return a['b']; // No problem!
}
return 42;
}
function f2(a: A) {
const key = 'b';
if (key in a) {
return a[key]; // Property 'b' does not exist on type 'A'
}
return 42;
}
Run Code Online (Sandbox Code Playgroud)
为什么 of 的类型没有a缩小为{b: number}in f2?(因为它是为了f1)
jca*_*alz 10
这本质上是与microsoft/TypeScript#10530相同的问题;控制流分析的类型缩小仅发生在直接像文字一样的属性上"b",而不发生在类型是文字类型的任意表达式上。Issue #10530 讨论通过属性访问缩小范围...例如a.bor a["b"],它确实会导致a缩小,而 vsa[key]则不会。
正如您所注意到的,这种情况也发生在in运算符类型保护(如在microsoft/TypeScript#15256中实现)中,其中"b" in a缩小了 的类型a,但key in a没有。#10530(早于类型in保护)中没有明确提到这一点,但我认为没有另一个专门与此相关的现有问题。
根据microsoft/TypeScript#10565,解决 #10530 中的问题的初步尝试是,为任意文本类型表达式添加类型保护功能会显着恶化编译器性能。也许对所有x in y检查执行额外分析比对所有y[x]属性访问执行额外分析更便宜,但至少到目前为止没有人太在意。
你总是可以在 GitHub 中打开你自己的问题(许多问题最终都是重复的,我不能 100% 确定这不会被视为 #10530 的重复,或者没有其他问题)重复),但实际上,它可能不会很快改变。
如果您想要一种解决方法来解决不能仅替换key为字符串文字的情况,您可以编写自己的用户定义类型保护函数,称为hasProp(obj, prop). 该实现只会返回prop in obj,但其类型签名明确表示true结果应obj缩小为仅具有类型键的那些联合成员prop:
function hasProp<T extends object, K extends PropertyKey>(
obj: T, prop: K
): obj is Extract<T, { [P in K]?: any }> {
return prop in obj;
}
Run Code Online (Sandbox Code Playgroud)
然后在您的函数中替换key in a为hasProp(a, key):
function f3(a: A) {
const key = 'b';
if (hasProp(a, key)) {
return a[key]; // okay
}
return 42;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3763 次 |
| 最近记录: |