我注意到,通过赋值缩小类型的工作方式有所不同,具体取决于我们使用的语法:点表示法或对象文字表示法。这是为什么?这是两个例子。
type MyObj = { x?: number | string }
let obj1: MyObj = {}
obj1.x = 1 // assign x with dot
obj1.x // number
let obj2: MyObj;
obj2 = { x: 1 }; // assign x with object literal
obj2.x // number | string | undefind
我预计在这两种情况下会有相同的行为。
工会范围缩小。在第一个示例中,您直接分配给属性
x
,它是联合类型 number | string | undefined
,因此控制流将其范围缩小到 number
的其余范围。但在第二个示例中,您分配给一个不是联合的对象,因此控制流不会缩小它的范围。
缩小也仅发生在当前范围内,例如,您将在嵌套函数中失去它。
我明白了,似乎 TS 可以解决这个问题,但遗憾的是它没有,至少目前,他们不断改进控制流分析。
如果将类型更改为联合,则分配文字对象将缩小范围:
type MyObj = { x?: number | string }
let obj1: MyObj = {}
obj1.x = 1 // assign x with dot
obj1.x // number
function anotherScope() {
obj1.x // number | string | undefind
}
let obj2: MyObj;
obj2 = { x: 1 }; // assign x with object literal
obj2.x // number | string | undefind
obj2.x = 2;
obj2.x // number
let obj3: { x: number } | { x: string } | { x?: undefined };
obj3 = { x: 1 } ; // assign x with object literal
obj3.x // number, narrowed to first member of the union
let obj4: { x?: number } | { x?: string }
obj4 = { x: 1 } ; // assign x with object literal
obj4.x // number | undefind, narrowed to first member of the union