我使用的是 Typescript 3.7.2,但它也发生在早期的 Typescript 版本中。strictNullChecks 处于开启状态。
我有这个小代码片段:
interface Test {
one: boolean;
two: boolean;
}
function getPropOrFalse(someTest: Partial<Test>, prop: keyof Test): boolean {
if (prop in someTest) {
const value = someTest[prop];
return value; // <-- typescript determines this still to be boolean | undefined. Why??
}
return false;
}
Run Code Online (Sandbox Code Playgroud)
我不明白,为什么我的常数在那个检查之后value仍然存在。有谁知道它背后的原理吗?boolean|undefinedprop in someTest
编辑:顺便说一下,更改prop in someTest为someTest[prop] !== undefined不会改变结果。
这里发生了一些事情。第一的:
打字稿没有多少津贴的区别那些特性/功能参数之间缺少和那些是存在的,但undefined。“可选性”注释foo?: Bar代表这两种情况。并且,Partial<Test>计算为具有两个可选属性的类型,相当于{one?: boolean, two?: boolean}.
因此我可以称之为:
getPropOrFalse({ one: undefined }, "one"); // oops
Run Code Online (Sandbox Code Playgroud)
这就是编译器现在的方式(直到并且除非以某种方式解决microsoft/TypeScript#13195)。我可以想象跳过很多圈子来使调用签名getPropOrFalse()禁止someTest带有present-but-undefined属性的参数,但是编译器可能仍然不理解 的实现内部的含义getPropOrFalse(),因此您必须使用断言之类的。我会说不与类型系统作斗争并允许存在但undefined属性更健康。
在in一个属性的存在运营商的检查,但它不检查属性的值是undefined或不是。因此,in操作符不足以检查可选属性,而typeof foo.prop === "undefined"实际检查属性是否undefined存在。(是的,我知道,不是在您的情况下;请继续阅读!)可以通过以下方式证明这种差异:
function getOneOrFalse(someOne: { one?: boolean }): boolean {
if ("one" in someOne) {
return someOne.one; // error! boolean | undefined
}
if (typeof someOne.one !== "undefined") {
return someOne.one; // okay
}
return false;
}
Run Code Online (Sandbox Code Playgroud)
但是,显然,更改为typeof someTest[prop] === "undefined"不适用于您的getPropOrFalse()功能:
function badGetPropOrFalse(someTest: Partial<Test>, prop: keyof Test): boolean {
if (typeof someTest[prop] !== "undefined") {
return someTest[prop]; // still error! boolean | undefined
}
return false;
}
Run Code Online (Sandbox Code Playgroud)
是什么赋予了?这是第二件事:
当属性不是单个文字时,问题与尝试对索引属性访问(带括号)进行类型保护有关。在您的情况下,因为是一个变量,并且是联合类型,编译器无法(或不愿意)执行控制流分析缩小(请参阅 microsoft/TypeScript#10530)。我想有人试图解决这个问题,但它对性能产生了重大影响,因此它似乎已被放弃(或至少被推迟)。我预计性能会受到一些影响,因为为了使其正常工作,编译器必须在由变量索引时对“变量的类型”进行特定跟踪prop"one" | "two"someTestprop”,这不能简单地转化为仅缩小 的类型someTest。(毕竟,如果我有两个属性,prop1并且prop2都是 type keyof Test,并且我检查了someTest[prop1],那么它将与 的类型无关someTest[prop2],尽管事实上prop1和prop2是相同的根据类型系统类型。)
解决这个问题的方法是减轻编译器跟踪按变量索引的变量的负担,并首先将其分配给一个新const变量,如另一个答案中所述:
function getPropOrFalse(someTest: Partial<Test>, prop: keyof Test): boolean {
const val = someTest[prop]; // boolean | undefined
if (typeof val !== "undefined") {
return val; // okay
}
return false;
}
Run Code Online (Sandbox Code Playgroud)
当然,一旦我们开始像这样重构,我们就可以一路走下去:
function simplestGetPropOrFalse(someTest: Partial<Test>, prop: keyof Test): boolean {
return someTest[prop] ?? false;
}
Run Code Online (Sandbox Code Playgroud)
(它使用新添加的空合并运算符)
好的,希望这有助于解释发生了什么。祝你好运!
| 归档时间: |
|
| 查看次数: |
425 次 |
| 最近记录: |