利用 TypeScript 联合类型以及类型保护机制来正确推断类型

假设有两个接口 A 和 B

假设有个对象 Obj 在程序运行过程中,有可能为 A 类型也有可能为 B 类型,

这时候就可以利用联合类型 Obj: A | B,多个类型用 | 分隔

利用 TypeScript 联合类型以及类型保护机制来正确推断类型插图
举个栗子

但是需要注意的是,这时候 TypeScript 只能推断 A 和 B 的共有属性

Interface A {
name: string
age: number
}
Interface B {
name: string
sex: 'female' | 'male'
}

这时候如果访问 Obj.age 或者 Obj.sex TS就会报错提示类型上没有该属性。而Obj.name 则推断出类型为 string.

再进一步,在运行中,我们如何判断当前Obj是A还是B类型呢?
如果在Obj是A类型的时候调用Obj.sex就会报错。
在以前的 JS 中我们可以这样

if (Obj.sex) {
    Obj.age;
}
else if (Obj.age) {
    Obj.sex;
}

在 TS 可以这样

if ((<A>Obj).age) {
    (<A>Obj).age;
}
else {
    (<B>Obj).sex;
}

但是这样非常麻烦,这时候就该类型保护登场了,我们一旦检查过类型,就能在之后的每个分支里清楚地知道Obj当前的类型是A还是B。

const isObjA = (Obj: A | B): Obj is A => true
//我们现在只需要
if(isObjA) {
//这里就能 
Obj.age
} else {
//这里可以
Obj.sex
}//现在都不会报错了

下面是例子

利用 TypeScript 联合类型以及类型保护机制来正确推断类型插图1
利用 TypeScript 联合类型以及类型保护机制来正确推断类型插图2
利用 TypeScript 联合类型以及类型保护机制来正确推断类型插图3

Typescript参考文档