前面我們學(xué)的數(shù)字類型、字符串類型、布爾類型、數(shù)組類型等等可能都是我們比較熟悉的數(shù)據(jù)類型,在其他計算機(jī)語言中也能經(jīng)常見到。而本節(jié)我們要學(xué)習(xí)的是 TypeScript 中的高級類型,例如交叉類型、聯(lián)合類型、類型別名、字面量類型等。
交叉類型
交叉類型是將多個類型合并為一個類型。可以通過 & 來實現(xiàn)合并,生成的新類型包含了所需的所有類型的特性。
舉一個例子,假設(shè) A、B、C 是三種不同的數(shù)據(jù)類型, 我們將三種類型合并為一個新的交叉類型 A & B & C ,那么使用這個交叉類型聲明的對象可以同時包含 A、B、C 這個三種類型的成員。
一般交叉類型大多用于混入(mixins),或其他不適合典型面向?qū)ο竽P偷牡胤绞褂谩T?JavaScript 里發(fā)生這種情況的場合很多。
示例:
我們來看一個簡單的例子,下面 User 和 Student 是我們定義好的兩個接口:
interface User {
id: number,
username: string,
age: number
}
interface Student{
id: number,
score: number[],
}
let cross: User & Student; // 交叉類型
// 變量cross擁有兩個接口中的所有屬性
cross.id;
cross.username;
cross.age;
cross.score;
交叉類型 User & Student 就包含了上述兩個接口中的所有屬性,而通過交叉類型聲明的變量 cross,擁有兩個接口中的所有的屬性。
但是這種方式也需要注意一個問題,就是如果兩個接口中有相同的屬性,但是屬性的類型不同,這樣就會造成沖突,不可以賦值。例如:

聯(lián)合類型
聯(lián)合類型可以通過管道將變量設(shè)置多種類型,賦值時可以根據(jù)設(shè)置的類型來賦值。也就是說聯(lián)合類型的變量可以是指定的幾種數(shù)據(jù)類型中的一種,我們可以通過豎線 | 來分隔不同的類型。
語法格式:
Type1|Type2|Type3
需要注意的是,聲明為聯(lián)合類型的變量,只能賦值指定的類型的值,如果賦值其他類型的值也會報錯喲。
示例:
例如我們聲明一個聯(lián)合類型的變量 our:
let our:number|string|boolean;
our = 18;
our = 'xkd';
our = true;
上述的代碼表示變量 our 的值可以是 number 類型、string 類型或者 boolean 類型中的一種。如果我們給變量 our 賦值為這三個指定數(shù)據(jù)類型以外的類型值,則會導(dǎo)致報錯喲。
類型別名
我們在使用類型時,可以通過 type 關(guān)鍵字為類型起一個別名,類型別名較多應(yīng)用于聯(lián)合類型、交叉類型這種復(fù)合類型,這樣可以避免我們重復(fù)它們的定義。
起別名并不會新建一個類型,只是創(chuàng)建了一個新的名字來引用那個類型。
示例:
例如給一個自定義的聯(lián)合類型加上一個類型別名 admix,然后我們在使用這個聯(lián)合類型來聲明變量的時候,就只需要指定變量為 admix 類型即可。這樣我們就不需要多次定義 number|string|boolean ,而直接使用別名 admix 來引用此類型就行了:
type admix = number|string|boolean; // 給聯(lián)合類型加上別名
let a:admix = 100;
let b:admix = 'xkd';
let c:admix = true;
console.log(a);
console.log(b);
console.log(c);
編譯成 JavaScript 代碼:
var a = 100;
var b = 'xkd';
var c = true;
console.log(a);
console.log(b);
console.log(c);
輸出:
100
xkd
true
字面量類型
在 TypeScript 中,字面量類型允許我們指定必須的固定值,通過分隔符 | 將不同字面量分隔,且也可以通過 type 關(guān)鍵字為自定義的字面量類型加上別名。
示例:
例如當(dāng)變量的值為”小飛俠”就是“水星仔”其中之一,那我們就可以將這兩個值構(gòu)成一個聯(lián)合類型字面量,:
type names = '小飛俠' | '水星仔';
let a:names = '小飛俠';
let b:names = '水星仔';
上述代碼中通過別名 names 將變量 a、b 聲明為我們自定義的字面量,那么這兩個變量的值僅能為“小飛俠” 或者 “水星仔” 其中之一,否則會報錯。
一般我們是很少直接這樣使用的,在一些特殊情況下,例如使用字符串字面量類型來區(qū)分函數(shù)重載,或用于縮小范圍調(diào)試 bug 等,可以這樣使用。
訪問聯(lián)合類型的屬性或者方法
當(dāng) TypeScript 不確定一個聯(lián)合類型的變量到底是哪個類型的時候,我們只能訪問此聯(lián)合類型的所有類型里共有的屬性或方法。
示例:
例如我們在一個函數(shù) info 中定義兩個參數(shù),參數(shù) username 的類型為 string 類型,而 age 的類型為一個聯(lián)合類型,可以是 string 類型或 number 類型:
function info( username: string, age : string | number) {
console.log(age.length); // 報錯
}
我們在使用 age 來訪問屬性 length 時會導(dǎo)致報錯,這是因為只有字符串類型中才有屬性 length,數(shù)字類型沒有這個屬性。 由于 length 并不是數(shù)字類型和字符串類型的共有屬性,所以被聲明為這個聯(lián)合類型的變量 age 不能訪問這個屬性。
function info( username: string, age : string | number) {
console.log(age.toString());
}
通過 age 來訪問 toString() 方法不會報錯,這是因為 toString() 方法是數(shù)字類型和字符串類型共有的方法,所以被聲明為聯(lián)合類型的 age 可以訪問這個方法。