首先先来描述一个需求场景,例若有一个建立用户和更新用户的功能,其中要传给服务端的字段除了「更新」须要多一个「id」属性之外其他属性都同样。typescript
在此我先定义一个接口来声明这个参数对象的类型:函数
interface Prop{
action:'create'|'update';
id?:string;
name:string;
}
复制代码
可是咱们发现,这个接口并不知足咱们的需求,由于咱们这样建立对象依然会经过:ui
const a:Prop = {
action:'create',
id:'1',
name:'zhangsan'
}
复制代码
这个类型并不会经过 action
的值来帮我判断是否应该有 id
字段。spa
接下来换个写法来改进一下:code
type Prop =
| {
action: "create";
name: string;
}
| {
action: "update";
id: string;
name: string;
};
const a: Prop = {
action: "update",
name: "zhangsan"
};
复制代码
这时若是咱们声明一个 Prop 类型的变量没有 id
属性,TypeScript 就会报出异常:对象
Property 'id' is missing in type '{ action: "update"; name: string; }' but required in type '{ action: "update"; id: string; name: string; }'.接口
这就顺利解决了咱们的问题,可是接着又遇到一个问题,当我在一个函数中传入 Prop 类型的参数,并使用了它的 id
属性时,TypeScript 又报了一个错误:ip
type Prop =
| {
action: "create";
name: string;
}
| {
action: "update";
id: string;
name: string;
};
function fn(e: Prop) {
console.log(e.id);
}
// Property 'id' does not exist on type '{ action: "create"; name: string; }'.
复制代码
原来是 TypeScript 并不肯定你传进来的对象的 action
为 update 仍是 create,因此继续改进一些代码来帮助 TypeScript 判断:string
type Prop =
| {
action: "create";
name: string;
}
| {
action: "update";
id: string;
name: string;
};
function fn(e: Prop) {
if (e.action === "create") {
console.log(e.name);
} else {
console.log(e.id);
}
}
复制代码
这样报错就顺利解决了。it
咱们一直在使用的 type Prop
这个类型就是一个可辨识联合,从上面的代码来看它有如下特色:
action
。