考虑以下示例:
class A {}
class B extends A {
foo() {
return 6;
}
}
const variable: A = new B();
const isValid = variable instanceof B;
if (isValid) {
variable.foo();
}
Run Code Online (Sandbox Code Playgroud)
调用.foo()时提示如下错误:
这是有道理的,因为variable它的类型是A。但仅当是 的实例variable.foo()时才会运行。variableB
这样做时不会出现此问题:
class A {}
class B extends A {
foo() {
return 6;
}
}
const variable: A = new B();
if (variable instanceof B) {
variable.foo();
}
Run Code Online (Sandbox Code Playgroud)
为什么条件存储在变量中而不是显式写入变量中很重要if?
TS4.4 更新:
TypeScript 4.4 将引入对别名条件的控制流分析的支持。这意味着您有时可以将类型保护的结果保存到consts 中并在以后使用它们。因此,您上面的代码将按预期工作,无需修改。
TS4.4 之前的答案:
microsoft/TypeScript#12184 (除其他外,请参阅该问题以获取指向它们的链接)有一个建议 ,允许将类型保护的结果存储到布尔变量中以供以后使用。虽然大多数人都同意拥有这个就好了,但该语言的首席架构师说:
这需要我们跟踪一个变量的特定值对其他变量意味着什么影响,这会给控制流分析器增加大量的复杂性(以及相关的性能损失)。尽管如此,我们仍会将其保留为建议。
为了扩展这一点,目前编译器认识到,在variable instanceof B已经测试和评估为 的代码块内true, 的类型variable 可以缩小为B... 但在该范围之外,编译器可以“忘记”这样的缩小:
if (variable instanceof B) {
variable.foo(); // okay
}
variable.foo(); // error
Run Code Online (Sandbox Code Playgroud)
为了使类似以下内容的工作正常进行:
const isValid = variable instanceof B;
if (isValid) {
variable.foo();
}
Run Code Online (Sandbox Code Playgroud)
不允许编译器“忘记”缩小范围,直到isValid它本身......或者任何依赖的内容isValid超出范围。表面上这似乎是合理的,但对于像这样的您需要这样的内存的情况,似乎在很多情况下不需要额外的工作。例如,如果你有这个:
const bar = Math.random() < 0.5 ? { a: 123, b: 456 } : undefined;
const baz = bar?.a;
Run Code Online (Sandbox Code Playgroud)
编译器是否应该“记住”这baz将是一个number当且仅当bar是一个{a: number, b: number}?也许......但除非后来有人真正使用这个事实,如:
const qux = typeof baz === "number" ? bar.b : 789;
Run Code Online (Sandbox Code Playgroud)
那么跟踪它只是浪费精力。
将来有人可能会设计出一种比当前情况更好的方法来做到这一点,同时又不会使控制流分析变得过于昂贵。也许想要在boolean变量上进行这种行为的人可以用类型谓词之类的东西手动注释它,正如有关相关问题的评论中提到的那样?
const isValid: variable is B = variable instanceof B; // not valid syntax now
Run Code Online (Sandbox Code Playgroud)
但目前,它还不是语言的一部分。如果您确实对此有强烈的感受,您可能需要转到相关的 GitHub 问题并向他们提供您的或描述您的用例,并解释为什么当前使用非存储类型保护的行为是不够的。如果有足够多的人这样做,就会增加最终实施某件事的机会。不过我不会指望它。
在可预见的未来,您最好立即使用类型保护,而不是尝试保存它们以供以后使用。接近这种“延迟”行为的一种方法是重构,以便您保存的内容比以下内容更具功能性boolean:
const varIfValid = variable instanceof B ? variable : undefined;
if (varIfValid) {
varIfValid.foo(); // okay
}
Run Code Online (Sandbox Code Playgroud)
这是有效的,因为varIfValidis 是一个比isB | undefined更直接与调用相关的联合。foo()true | false
| 归档时间: |
|
| 查看次数: |
1275 次 |
| 最近记录: |