在 TypeScript中西雀,可索引類型是指那些可以通過索引訪問其屬性值的類磺送,通常情況下车份,這些類型被定義為對象或數(shù)組谋减,用來模擬數(shù)組或字典的行為∩ㄕ樱可索引類型允許你定義一個接口來指定對象可以被哪些類型的鍵所索引出爹,這個定義的接口有一個索引簽名,用于描述可以使用的索引類型及其對應(yīng)的返回值類型缎除。
1严就、基本索引類型語法
你可以通過索引簽名(index signatures)
來定義可索引類型。索引簽名使用 []
來表示器罐,并且需要指定鍵的類型和值的類型梢为。常見的鍵類型包括 string
和 number
。注:現(xiàn)在只支持字符串
和數(shù)字
.
- 定義鍵值為數(shù)字的索引類型
interface StringArray {
[index: number]: string;
}
例子中StringArray
是一個具有數(shù)字索引的類型轰坊,并且每個索引對應(yīng)的值都是字符串類型铸董,這意味著任何數(shù)字都可以作為索引,并且對應(yīng)的值必須是數(shù)字肴沫。
let _myArray: StringArray = ["Bob", "Fred"]
let _myStr: string = _myArray[0];
console.log(_myStr); //Bob
//或
_myStr = _myArray["0"]
console.log(_myStr); //Bob
為什么_myArray[0]和_myArray["0"]都可以呢粟害,后面的
字符串索引與數(shù)字索引的關(guān)系
中會說明
- 定義鍵值為字符串的索引類型
- 基礎(chǔ)字符串索引類型的示例
interface NumberDictionary {
[key: string]: number;
}
例子中NumberDictionary
是一個具有字符串索引的類型,并且每個索引對應(yīng)的值都是數(shù)字類型颤芬。具體表示NumberDictionary
的屬性名稱為字符串類型悲幅,對應(yīng)的屬性值為數(shù)字類型套鹅。
let _myDict: NumberDictionary = {"a":10, "b":20}
let _myValue:number = _myDict["a"]
console.log(_myValue); // 10
- 再實現(xiàn)個索引值類型為任意值的示例
interface StringDictionary {
[key: string]: any; // 任何字符串都可以作為鍵,值的類型是任意類型
}
在這個例子中汰具,StringDictionary 接口定義了一個字符串索引簽名卓鹿,這意味著任何字符串都可以作為鍵,并且對應(yīng)的值可以是任意類型郁副。
let _anyDict: StringDictionary = {name: "Alice", age: 25, location: "Wonderland" }
console.log(_anyDict["name"]); //輸出:Alice
console.log(_anyDict.name); //輸出:Alice
console.log(_anyDict["age"]); //輸出:25
console.log(_anyDict.age); //輸出:25
console.log(_anyDict["location"]); //輸出:Wonderland
console.log(_anyDict.location); //輸出:Wonderland
注:我們發(fā)現(xiàn)
["name"]
和.name
的取值方式都可獲得正確的索引值减牺,表明字符串索引類型聲明了obj.property
和obj["property"]
兩種形式都可以獲取索引值
2、字符串索引與數(shù)字索引的關(guān)系
聲明索引類型時可以同時定義字符串和數(shù)字索引簽名存谎,但 TypeScript
要求數(shù)字索引的返回類型必須是字符串索引返回類型的子類型拔疚,這是因為在JavaScript
中,數(shù)字索引會首先被轉(zhuǎn)換為字符串鍵既荚。
例如:定義了一個數(shù)字索引類型稚失,用
100
(一個number
)去獲取索引值,這時等同于使用"100"
(一個string
)去索引恰聘。
interface Animal {
name: string;
}
interface Dog extends Animal {
breed: string;
}
interface AnimalDictionary {
[index: number]: Dog;
[key: string]: Animal
}
在這里句各,數(shù)字索引number
返回的是Dog
類型,而字符串索引string
返回的是Animal
類型晴叨。因為Dog
是Animal
的子類型凿宾,所以這是合法的
// 定義三個動物
let _dog_1: Dog = {
name: "小白",
breed: "京巴"
}
let _dog_2: Dog = {
name: "小黑",
breed: "柴犬"
}
let _animal_1: Animal = {
name: "花花"
}
- 第一種使用方式
let _animalInfo = {
animal1: _dog_1,
100:_dog_1,
animal2: _dog_2,
200:_dog_2,
animal3:_animal_1,
300:_animal_1
}
console.log(_animalInfo["animal1"]); //輸出:{ name: '小白', breed: '京巴' }
console.log(_animalInfo[100]); //輸出:{ name: '小白', breed: '京巴' }
console.log(_animalInfo["animal3"]); //輸出:{ name: '花花' }
console.log(_animalInfo[300]); //輸出:{ name: '花花' }
- 第二種使用方式
let _animalArr = [_dog_1, _dog_2, _animal_1]
console.log(_animalArr[0]); //輸出:{ name: '小白', breed: '京巴' }
console.log(_animalArr[1]); //輸出:{ name: '小黑', breed: '柴犬' }
console.log(_animalArr[2]); //輸出:{ name: '花花' }
3.索引簽名與屬性的關(guān)系
當(dāng)在一個接口中同時定義了索引簽名和具體屬性時,所有具體屬性的類型必須符合索引簽名的約束兼蕊。
- 索引簽名與具體屬性
當(dāng)一個接口既有索引簽名初厚,又有具體的屬性時,索引簽名的類型會影響具體屬性的類型孙技,反之亦然产禾。具體來說,所有具體屬性的類型必須兼容索引簽名的返回類型牵啦。
錯誤聲明方式:
interface MyDictionary {
[key: string]: number;
length: number; // 合法亚情,屬性類型與索引簽名一致
name: string // 非法,屬性類型與索引簽名類型沖突,`name`的類型與索引類型返回值的類型不匹配
// 類型“string”的屬性“name”不能賦給“string”索引類型“number”哈雏。
}
在上面的例子中楞件,length
屬性是合法的,因為它的類型number
與索引簽名[key: string]: number
類型一致裳瘪。但是name: string
屬性則會報錯履因,因為string
類型與索引簽名返回的number
類型不兼容。
正確聲明方式:
interface MyDictionary {
[key: string]: any;
//或
//[key: string]: number | string;
length: number;
name: string;
}
let _myInfo: MyDictionary = {length: 180, name: "bob", city: "北京", age: 24}
console.log(_myInfo["length"]); //輸出:180
console.log(_myInfo["name"]); //輸出:bob
console.log(_myInfo["city"]); //輸出:北京
console.log(_myInfo["age"]); //輸出:24
- 具體屬性可以細化類型
盡管索引簽名限制了屬性的類型盹愚,但具體的屬性可以是索引簽名的類型的子類型。因此站故,具體屬性可以比索引簽名的類型更加精確皆怕。
interface MyDictionary {
[key: string]: number;
specialProperty: 42; // 具體屬性是索引簽名類型的子類型
}
在這個例子中毅舆,specialProperty 的類型是字面量類型 42,它是 number 類型的一個子類型愈腾,因此這種定義是合法的憋活。
- 混合使用索引簽名和屬性
在一些場景下,具體屬性和索引簽名可以混合使用虱黄,但需要謹慎處理類型的一致性悦即。如果你希望某些屬性具有不同的類型,可以通過類型聯(lián)合來實現(xiàn)
interface MyDictionary {
[key: string]: number | string;
id: number;
name: string;
}
在這個例子中橱乱,[key: string]: number | string
允許所有屬性的值既可以是 number
也可以是 string
辜梳,因此 id
和 name
屬性都合法。
4.索結(jié)合使用多種索引簽名
可以在一個接口中定義多個索引簽名泳叠,只要它們的鍵類型不同:
interface MixedDictionary {
[key: string]: string | number;
[index: number]: string;
}
let mixed: MixedDictionary = {
0: 'zero',
one: 1,
two: 'two'
};
console.log(mixed[0]);
console.log(mixed["one"]);
在這個例子中作瞄,MixedDictionary
接口既支持字符串索引也支持數(shù)字索引,并且值可以是 string
或 number
危纫。
5.索只讀索引簽名
如果你希望索引簽名是只讀的宗挥,可以使用 readonly 關(guān)鍵字,防止了給索引賦值:
interface ReadonlyStringDictionary {
readonly [key: string]: string;
}
let roObj: ReadonlyStringDictionary = {
prop: "value"
};
// roObj.prop = "newValue"; // 錯誤:不能修改只讀屬性
interface ReadonlyStringArray {
readonly [index: number]: string;
}
let myArray: ReadonlyStringArray = ["Alice", "Bob"];
myArray[2] = "Mallory"; // error:你不能設(shè)置myArray[2]种蝶,因為索引簽名是只讀的契耿。
總結(jié)
- 數(shù)字索引類型:
[index: number]: Type
。 - 字符串索引類型:
[key: string]: Type
螃征。 - 數(shù)字索引類型的返回值必須是字符串索引類型的子類型搪桂。
- 索引簽名定義了對象中屬性的類型規(guī)則,并且所有屬性都必須與索引簽名類型兼容会傲。
這些特性使 TypeScript
能夠強類型地描述對象锅棕、數(shù)組等數(shù)據(jù)結(jié)構(gòu)。通過使用可索引類型淌山,你可以更靈活地定義和操作那些具有動態(tài)結(jié)構(gòu)的數(shù)據(jù)集合裸燎。這對于處理數(shù)據(jù)存儲、配置對象等場景非常有用泼疑。