TypeScript:聲明可索引類型

在 TypeScript中西雀,可索引類型是指那些可以通過索引訪問其屬性值的類磺送,通常情況下车份,這些類型被定義為對象或數(shù)組谋减,用來模擬數(shù)組或字典的行為∩ㄕ樱可索引類型允許你定義一個接口來指定對象可以被哪些類型的鍵所索引出爹,這個定義的接口有一個索引簽名,用于描述可以使用的索引類型及其對應(yīng)的返回值類型缎除。

1严就、基本索引類型語法
你可以通過索引簽名(index signatures)來定義可索引類型。索引簽名使用 []來表示器罐,并且需要指定鍵的類型和值的類型梢为。常見的鍵類型包括 stringnumber。注:現(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)系中會說明

  • 定義鍵值為字符串的索引類型
  1. 基礎(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
  1. 再實現(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.propertyobj["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類型晴叨。因為DogAnimal的子類型凿宾,所以這是合法的

// 定義三個動物
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辜梳,因此 idname 屬性都合法。

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ù)字索引,并且值可以是 stringnumber危纫。

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ù)存儲、配置對象等場景非常有用泼疑。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末德绿,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子退渗,更是在濱河造成了極大的恐慌移稳,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件会油,死亡現(xiàn)場離奇詭異个粱,居然都是意外死亡,警方通過查閱死者的電腦和手機翻翩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進店門都许,熙熙樓的掌柜王于貴愁眉苦臉地迎上來稻薇,“玉大人,你說我怎么就攤上這事胶征∪担” “怎么了?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵睛低,是天一觀的道長案狠。 經(jīng)常有香客問我,道長钱雷,這世上最難降的妖魔是什么骂铁? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮急波,結(jié)果婚禮上从铲,老公的妹妹穿的比我還像新娘。我一直安慰自己澄暮,他們只是感情好名段,可當(dāng)我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著泣懊,像睡著了一般伸辟。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上馍刮,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天信夫,我揣著相機與錄音,去河邊找鬼卡啰。 笑死静稻,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的匈辱。 我是一名探鬼主播振湾,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼亡脸!你這毒婦竟也來了押搪?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤浅碾,失蹤者是張志新(化名)和其女友劉穎大州,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體垂谢,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡厦画,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了滥朱。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片根暑。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡娃豹,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出购裙,到底是詐尸還是另有隱情,我是刑警寧澤鹃栽,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布躏率,位于F島的核電站,受9級特大地震影響民鼓,放射性物質(zhì)發(fā)生泄漏薇芝。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一丰嘉、第九天 我趴在偏房一處隱蔽的房頂上張望夯到。 院中可真熱鬧,春花似錦饮亏、人聲如沸耍贾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽荐开。三九已至,卻和暖如春简肴,著一層夾襖步出監(jiān)牢的瞬間晃听,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工砰识, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留能扒,地道東北人。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓辫狼,卻偏偏與公主長得像初斑,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子予借,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,976評論 2 355

推薦閱讀更多精彩內(nèi)容