聯(lián)合類型
聯(lián)合類型(Union Types)表示取值可以為多種類型中的一種捧韵。
let myFavoriteNumber: string | number;
myFavoriteNumber = 'seven';
myFavoriteNumber = 7;
聯(lián)合類型使用 |
分隔每個類型丝蹭。
這里的 let myFavoriteNumber: string | number 的含義是互亮,允許 myFavoriteNumber 的類型是 string 或者 number犁享,但是不能是其他類型。
當 TypeScript 不確定一個聯(lián)合類型的變量到底是哪個類型的時候豹休,我們只能訪問此聯(lián)合類型的所有類型里共有的屬性或方法:
function getString(something: string | number): string {
return something.toString();
}
對象類型(接口)
在 TypeScript 中炊昆,我們使用接口(Interfaces)來定義對象的類型。
在面向?qū)ο笳Z言中,接口(Interfaces)是一個很重要的概念凤巨,它是對行為的抽象视乐,而具體如何行動需要由類(classes)去實現(xiàn)(implements)。
TypeScript 中的接口是一個非常靈活的概念敢茁,除了可用于對類的一部分行為進行抽象以外佑淀,也常用于對「對象的形狀(Shape)」進行描述。
interface Person {
name: string;
age: number;
}
let tom: Person = {
name: 'Tom',
age: 25
};
賦值的時候卷要,變量的形狀必須和接口的形狀保持一致渣聚。定義的變量比接口少了一些屬性或者是多了一些屬性都是不允許的
有時我們希望不要完全匹配一個形狀独榴,那么可以用可選屬性(仍然不允許添加未定義的屬性)
interface Person {
name: string;
age?: number;
}
let tom: Person = {
name: 'Tom'
};
interface Person {
name: string;
age?: number;
}
let tom: Person = {
name: 'Tom',
age: 25
};
這時候我們希望一個接口允許有任意的屬性僧叉,可以使用如下方式:
使用 [propName: string] 定義了任意屬性取 string 類型的值。
interface Person {
name: string;
age?: number;
[propName: string]: any;
}
let wang: Person = {
name: "wang",
sex:"boy"
}
需要注意的是棺榔,一旦定義了任意屬性瓶堕,那么確定屬性和可選屬性的類型都必須是它的類型的子集:
interface Person {
name: string;
age?: number;
[propName: string]: string;
}
let tom: Person = {
name: 'Tom',
age: 25,
gender: 'male'
};
// index.ts(3,5): error TS2411: Property 'age' of type 'number' is not assignable to string index type 'string'.
// index.ts(7,5): error TS2322: Type '{ [x: string]: string | number; name: string; age: number; gender: string; }' is not assignable to type 'Person'.
// Index signatures are incompatible.
// Type 'string | number' is not assignable to type 'string'.
// Type 'number' is not assignable to type 'string'.
任意屬性的值允許是 string,但是可選屬性 age 的值卻是 number症歇,number 不是 string 的子屬性郎笆,所以報錯了。
另外忘晤,在報錯信息中可以看出宛蚓,此時 { name: 'Tom', age: 25, gender: 'male' } 的類型被推斷成了 { [x: string]: string | number; name: string; age: number; gender: string; },這是聯(lián)合類型和接口的結(jié)合设塔。
我們希望對象中的一些字段只能在創(chuàng)建的時候被賦值凄吏,那么可以用 readonly 定義只讀屬性:
interface Person {
readonly id: number;
name: string;
age?: number;
[propName: string]: any;
}
let tom: Person = {
id: 89757,
name: 'Tom',
gender: 'male'
};
tom.id = 9527;
// index.ts(14,5): error TS2540: Cannot assign to 'id' because it is a constant or a read-only property.
上例中,使用 readonly 定義的屬性 id 初始化后闰蛔,又被賦值了痕钢,所以報錯了。
只讀的約束存在于第一次給對象賦值的時候序六,而不是第一次給只讀屬性賦值的時候:
interface Person {
readonly id: number;
name: string;
age?: number;
[propName: string]: any;
}
let tom: Person = {
name: 'Tom',
gender: 'male'
};
tom.id = 89757;
// index.ts(8,5): error TS2322: Type '{ name: string; gender: string; }' is not assignable to type 'Person'.
// Property 'id' is missing in type '{ name: string; gender: string; }'.
// index.ts(13,5): error TS2540: Cannot assign to 'id' because it is a constant or a read-only property.
上例中任连,報錯信息有兩處,第一處是在對 tom 進行賦值的時候例诀,沒有給 id 賦值随抠。
第二處是在給 tom.id 賦值的時候,由于它是只讀屬性繁涂,所以報錯了拱她。