此爲高級類型的第一部分,學習交叉類型(Intersection Types)、聯合類型(Union Types)以及在使用以上類型時如何區分具體類型。javascript
交叉類型把幾個類型的成員合併,造成一個擁有這幾個類型全部成員的新類型。從字面上理解,可能會誤認爲是把取出幾個類型交叉的(即交集)成員。java
交叉類型的使用場景:Mixins、不適合用類來定義。es6
我感受,交叉類型和Mixins有一點區別:交叉類型只是一個類型聲明,用於類型約束;Mixins會給類增長成員,new對象時,對象會包含增長的成員屬性。
咱們看一看示例:post
改自官方示例,官方示例有2個小問題:會提示不存在屬性「hasOwnProperty」;另外, es6下prototype是不能夠枚舉的,沒法經過枚舉合併類屬性。
interface IAnyObject { [prop: string]: any } function extend<First extends IAnyObject, Second extends IAnyObject>(first: First, second: Second): First & Second { const result: Partial<First & Second> = {}; for (const prop in first) { if (first.hasOwnProperty(prop)) { (result as First)[prop] = first[prop]; } } for (const prop in second) { if (second.hasOwnProperty(prop)) { (result as Second)[prop] = second[prop]; } } return result as First & Second; } interface IPerson { name: string, age: number } interface IOrdered { serialNo: number, getSerialNo(): number } const personA: IPerson = { name: 'Jim', age: 20 } const orderOne: IOrdered = { serialNo: 1, getSerialNo: function () { return this.serialNo } } const personAOrdered = extend<IPerson, IOrdered>(personA, orderOne); console.log(personAOrdered.getSerialNo());
聯合類型與交叉類型相似,均可以擁有多個類型的能力,區別是:聯合類型一次只能一種類型;而交叉類型每次都是多個類型的合併類型。學習
聯合類型在實際項目中,使用場景比交叉類型普遍得多。this
function padLeft(value: string, padding: number | string) { if (typeof padding === "number") { return Array(padding + 1).join(" ") + value; } if (typeof padding === "string") { return padding + value; } return value; } padLeft("Hello world", 4);
type Scores = 1 | 2 | 3 | 4 | 5; function rating(score: Scores) { console.log(`Set score ${score}`); } rating(3); // error // rating(6);
枚舉也能夠實現,可是這樣更簡潔。prototype
function f(sn: string | null): string { if (typeof sn === null) { return 'default'; } else { return sn; } }
type Method = 'get' | 'post';
使用聯合類型時,咱們是沒法知道編譯時的具體類型的,因此在運行時必需要肯定類型。因此代碼中須要作類型保護和類型區分。code
爲何叫類型保護?由於在運行時,必須知道明確類型,不然可能會訪問一個不存在的成員屬性,致使程序出錯。對象
自定義類型保護ip
// 先判斷是否存在成員屬性 if(pet.swim) { }
in操做符
// 先判斷是否存在成員屬性 if('swim' in pet) { }
typeof操做符
function f(sn: string | number): string { if (typeof sn === 'number') { return sn.toString(); } else { return sn; } }
instanceof操做符
// 判斷實例原型 if(pet instanceof Fish) { }
類型斷言
function f(sn: string | null): string { if (sn === null) { return "default"; } else { return sn; } }
聯合類型應用極普遍,能夠多實踐。