首先先來描述一個需求場景,例若有一個建立用戶和更新用戶的功能,其中要傳給服務端的字段除了「更新」須要多一個「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
。