TypeScript 中如何限制對(duì)象鍵名的取值范圍
當(dāng)我們使用 TypeScript 時(shí),我們想利用它提供的類(lèi)型系統(tǒng)限制代碼的方方面面,對(duì)象的鍵值,也不例外。
譬如我們有個(gè)對(duì)象存儲(chǔ)每個(gè)年級(jí)的人名,類(lèi)型大概長(zhǎng)這樣:
type Students = Record<string, string[]>;
理所當(dāng)然地,數(shù)據(jù)就是長(zhǎng)這樣:
const students: Students = { Freshman: ["David", "John"], sophomore: [], Junior: ["Lily"], Senior: ["Tom"], };
限制對(duì)象鍵名為枚舉
上面數(shù)據(jù)類(lèi)型的問(wèn)題是,年級(jí)是有限的幾種可值取,而該對(duì)象上可任意添加屬性,這樣顯得數(shù)據(jù)不夠純粹。
所以我們新增枚舉,列出可取的值:
export enum Grade { Freshman, sophomore, Junior, Senior, }
現(xiàn)在,把對(duì)象的鍵名限制為上面枚舉就行了。
- type Students = Record<string, string[]>; + type Students = Record<Grade, string[]>;
這樣我們的數(shù)據(jù)可寫(xiě)成這樣:
const students: Students = { [Grade.Freshman]: ["David", "John"], [Grade.sophomore]: [], [Grade.Junior]: ["Lily"], [Grade.Senior]: ["Tom"], // ❌ Object literal may only specify known properties, and 'blah' does not exist in type 'Students'.ts(2322) blah: ["some one"], };
這樣,限制住了對(duì)象身上鍵名的范圍,可以看到如果添加一個(gè)枚舉之外的鍵會(huì)報(bào)錯(cuò)。
更加語(yǔ)義化的枚舉值
但上面的做法還是有不妥之處,因?yàn)槊杜e值默認(rèn)是從 0 開(kāi)始的數(shù)字,這樣,作為鍵值就不夠語(yǔ)義了,這點(diǎn)從訪(fǎng)問(wèn)對(duì)象的屬性時(shí)體現(xiàn)了出來(lái):
修正我們的枚舉,用更加語(yǔ)義的文本作為其值:
export enum Grade { Freshman = "Freshman", sophomore = "sophomore", Junior = "Junior", Senior = "Senior", }
此時(shí)再使用該枚舉時(shí),得到的就不是無(wú)意義的數(shù)字了。
如果你愿意,枚舉值也可以是中文,
export enum Grade { Freshman = "大一萌新", sophomore = "大二學(xué)弟", Junior = "大三學(xué)妹", Senior = "大四老司機(jī)", }
使用時(shí)也是沒(méi)任何問(wèn)題的:
鍵值可選
上面的類(lèi)型定義還有個(gè)問(wèn)題,即,它要求使用時(shí)對(duì)象包含枚舉中所有值,比如 sophomore
這個(gè)年級(jí)中并沒(méi)有人,可以不寫(xiě),但會(huì)報(bào)錯(cuò)。
// ❌ Property 'sophomore' is missing in type '{ Freshman: string[]; Junior: string[]; Senior: string[]; }' but required in type 'Students'.ts(2741) const students: Students = { [Grade.Freshman]: ["David", "John"], // [Grade.sophomore]: [], [Grade.Junior]: ["Lily"], [Grade.Senior]: ["Tom"], };
所以,優(yōu)化類(lèi)型為可選:
type Students = Partial<Record<Grade, string[]>>;
假若可選的值不是通過(guò)枚舉定義,而是來(lái)自一個(gè)數(shù)組,
const grades = ["Freshman", "sophomore", "Junior", "Senior"];
這意味著我們需要提取數(shù)組中的值形成一個(gè)聯(lián)合類(lèi)型。
首先利用const assertions 把數(shù)組轉(zhuǎn)元組(Tuple)類(lèi)型,
const grades = <const>["Freshman", "sophomore", "Junior", "Senior"];
再利用 typeof
和 Lookup Types 得到最終的聯(lián)合類(lèi)型:
// 實(shí)際為 type Keys = "Freshman" | "sophomore" | "Junior" | "Senior" type Keys = typeof grades[number];
最后數(shù)據(jù)類(lèi)型和數(shù)據(jù)可寫(xiě)成:
type Students = Partial<Record<Keys, string[]>>; const students: Students = { Freshman: ["David", "John"], Junior: ["Lily"], Senior: ["Tom"], };
須知這種形式下,對(duì)象的 key 與原數(shù)組中元素其實(shí)沒(méi)有語(yǔ)法層面的關(guān)聯(lián),即,編輯器的「跳轉(zhuǎn)定義」是不可用的。
盡量還是保持代碼之間的關(guān)聯(lián)才能體現(xiàn)出 TypeScript 的作用,所以像這種只有類(lèi)型約束而無(wú)法建立關(guān)聯(lián)的操作是不建議的。
相關(guān)資源
The text was updated successfully, but these errors were encountered:
以上就是TypeScript 中限制對(duì)象鍵名的取值范圍的詳細(xì)內(nèi)容,更多關(guān)于TypeScript限制對(duì)象鍵名范圍的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Add a Picture to a Microsoft Word Document
Add a Picture to a Microsoft Word Document...2007-06-06Nodejs使用mysql模塊之獲得更新和刪除影響的行數(shù)的方法
業(yè)余時(shí)間玩nodejs的時(shí)候遇到的情況, 在使用mysql模塊連接mysql操作, 想在update, delete語(yǔ)句的時(shí)候, 想知道到底u(yù)pdate, delete成功了沒(méi)有2014-03-03JavaScript實(shí)現(xiàn)簡(jiǎn)單的輪播圖效果
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)簡(jiǎn)單的輪播圖效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-06-06微信小程序?qū)崿F(xiàn)定位及到指定位置導(dǎo)航的示例代碼
這篇文章主要介紹了微信小程序?qū)崿F(xiàn)定位及到指定位置導(dǎo)航的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08javascript實(shí)現(xiàn)獲取圖片大小及圖片等比縮放的方法
這篇文章主要介紹了javascript實(shí)現(xiàn)獲取圖片大小及圖片等比縮放的方法,涉及javascript針對(duì)圖形圖像相關(guān)屬性獲取與修改相關(guān)操作技巧,需要的朋友可以參考下2016-11-11jquery將標(biāo)簽元素的高設(shè)為屏幕的百分比
這篇文章主要介紹了js將標(biāo)簽元素的高設(shè)為屏幕的百分比,需要的朋友可以參考下2017-04-04javascript字符串拆分成單個(gè)字符相加和不超過(guò)10,求最終值
javascript字符串拆分成單個(gè)字符相加和不超過(guò)10,求最終值2008-09-09