淺談TypeScript 索引簽名的理解
我們用兩個(gè)對(duì)象來描述兩個(gè)碼農(nóng)的工資:
const salary1 = { baseSalary: 100_000, yearlyBonus: 20_000 }; const salary2 = { contractSalary: 110_000 };
然后寫一個(gè)獲取總工資的函數(shù)
function totalSalary(salaryObject: ???) { let total = 0; for (const name in salaryObject) { total += salaryObject[name]; } return total; } totalSalary(salary1); // => 120_000 totalSalary(salary2); // => 110_000
如果是你的,要如何聲明totalSalary()
函數(shù)的salaryObject
參數(shù),以接受具有字符串鍵和數(shù)字值的對(duì)象?
答案是使用一個(gè)索引簽名!
接著,我們來看看什么是 TypeScript
索引簽名以及何時(shí)需要它們。
1.什么是索引簽名
索引簽名的思想是在只知道鍵和值類型的情況下對(duì)結(jié)構(gòu)未知的對(duì)象進(jìn)行類型劃分。
它完全符合salary
參數(shù)的情況,因?yàn)楹瘮?shù)應(yīng)該接受不同結(jié)構(gòu)的salary
對(duì)象,唯一的要求是屬性值為數(shù)字。
我們用索引簽名來聲明salaryObject
參數(shù)
function totalSalary(salaryObject: { [key: string]: number }) { let total = 0; for (const name in salaryObject) { total += salaryObject[name]; } return total; } totalSalary(salary1); // => 120_000 totalSalary(salary2); // => 110_000
{[key: string]: number}
是索引簽名,它告訴TypeScript salaryObject
必須是一個(gè)以string
類型為鍵,以 number
類型為值的對(duì)象。
2. 索引簽名語法
索引簽名的語法相當(dāng)簡(jiǎn)單,看起來與屬性的語法相似,但有一點(diǎn)不同。我們只需在方括號(hào)內(nèi)寫上鍵的類型,而不是屬性名稱:{ [key: KeyType]: ValueType
}。
下面是一些索引簽名的例子。
string
類型是鍵和值。
interface StringByString { [key: string]: string; } const heroesInBooks: StringByString = { 'Gunslinger': '前端小智', 'Jack Torrance': '王大志' };
string
類型是鍵,值可以是 string
、number
或boolean
interface Options { [key: string]: string | number | boolean; timeout: number; } const options: Options = { timeout: 1000, timeoutMessage: 'The request timed out!', isFileUpload: false };
簽名的鍵只能是一個(gè) string
`、number
或 symbol
`。其他類型是不允許的。
3. 索引簽名的注意事項(xiàng)
TypeScript
中的索引簽名有一些注意事項(xiàng),需要注意。
3.1不存在的屬性
如果試圖訪問一個(gè)索引簽名為 { [key: string]: string
} 的對(duì)象的一個(gè)不存在的屬性,會(huì)發(fā)生什么?
正如預(yù)期的那樣,TypeScript
將值的類型推斷為 string
。但是檢查運(yùn)行時(shí)值,它是undefined
:
根據(jù) TypeScript
提示, value
變量是一個(gè) string
類型,但是它的運(yùn)行時(shí)值是 undefined
。
索引簽名只是將一個(gè)鍵類型映射到一個(gè)值類型,僅此而已。如果沒有使這種映射正確,值類型可能會(huì)偏離實(shí)際的運(yùn)行時(shí)數(shù)據(jù)類型。
為了使輸入更準(zhǔn)確,將索引值標(biāo)記為 string
或 undefined
。這樣,TypeScript
就會(huì)意識(shí)到你訪問的屬性可能不存在
3.2 string 和 number 鍵
假設(shè)有一個(gè)數(shù)字名稱的字典:
interface NumbersNames { [key: string]: string } const names: NumbersNames = { '1': 'one', '2': 'two', '3': 'three', // ... };
不會(huì),正常工作。
當(dāng)在屬性訪問器中作為鍵使用時(shí),JavaScript
隱式地將數(shù)字強(qiáng)制為字符串(names[1]
與names['1'
]相同)。TypeScript
也會(huì)執(zhí)行這個(gè)強(qiáng)制。
你可以認(rèn)為 [key: string
] 與 [key: string | number]
相同。
4.索引簽名與 Record<Keys, Type>對(duì)比
TypeScript
有一個(gè)實(shí)用類型 Record<Keys, Type>,
類似于索引簽名。
const object1: Record<string, string> = { prop: 'Value' }; // OK const object2: { [key: string]: string } = { prop: 'Value' }; // OK
那問題來了...什么時(shí)候使用 Record<Keys, Type>,
什么時(shí)候使用索引簽名?乍一看,它們看起來很相似
我們知道,索引簽名只接受 string
、number
或 symbol
作為鍵類型。如果你試圖在索引簽名中使用,例如,字符串字面類型的聯(lián)合作為鍵,這是一個(gè)錯(cuò)誤。
索引簽名在鍵方面是通用的。
但是我們可以使用字符串字面值的聯(lián)合來描述 Record<keys, Type>
中的鍵
type Salary = Record<'yearlySalary'|'yearlyBonus', number> const salary1: Salary = { 'yearlySalary': 120_000, 'yearlyBonus': 10_000 }; // OK
Record<Keys, Type>
是為了具體到鍵的問題。
建議使用索引簽名來注釋通用對(duì)象,例如,鍵是字符串類型。但是,當(dāng)你事先知道鍵的時(shí)候,使用Record<Keys, Type>
來注釋特定的對(duì)象,例如字符串字面量' prop1' | 'prop2'
被用于鍵值。
總結(jié):
如果你不知道你要處理的對(duì)象結(jié)構(gòu),但你知道可能的鍵和值類型,那么索引簽名就是你需要的。
索引簽名由方括號(hào)中的索引名稱及其類型組成,后面是冒號(hào)和值類型: { [indexName: KeyType]: ValueType }, KeyType
可以是一個(gè) string
、number
或 symbol
,而ValueType
可以是任何類型。
到此這篇關(guān)于淺談TypeScript 索引簽名的理解的文章就介紹到這了,更多相關(guān)TypeScript 索引簽名內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JS前端實(shí)現(xiàn)fsm有限狀態(tài)機(jī)實(shí)例詳解
這篇文章主要為大家介紹了JS前端實(shí)現(xiàn)fsm有限狀態(tài)機(jī)實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09關(guān)于JavaScript輪播圖的實(shí)現(xiàn)
這篇文章主要介紹了關(guān)于JavaScript輪播圖的實(shí)現(xiàn),下面文章主要是利用利用html 和 css 代碼實(shí)現(xiàn)輪播圖,詳細(xì)內(nèi)容請(qǐng)參考下面詳細(xì)內(nèi)容,希望對(duì)你有所幫助2021-11-11微信小程序 wx.request(object) API詳解及實(shí)例代碼
這篇文章主要介紹了微信小程序 wx.request(object) API詳解及實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2016-09-09JavaScript實(shí)現(xiàn)優(yōu)先級(jí)隊(duì)列
這篇文章主要介紹了JavaScript如何實(shí)現(xiàn)優(yōu)先級(jí)隊(duì)列,在計(jì)算機(jī)里,隊(duì)列是一種先進(jìn)先出的數(shù)據(jù)結(jié)構(gòu)。就跟我們平時(shí)排隊(duì)一樣,先到的排在前面,前面的優(yōu)先處理,下面我們就來看看在JavaScript里面的優(yōu)先隊(duì)列又當(dāng)如何2021-12-12lodash內(nèi)部方法getData和setData實(shí)例解析
本篇章我們將了解lodash里內(nèi)部關(guān)于Data的操作方法,重點(diǎn)關(guān)注getData、setData兩個(gè)內(nèi)部方法,同時(shí)由實(shí)現(xiàn)上引申其他內(nèi)部封裝的方法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08