TypeScript 中如何限制物件鍵名的取值範圍
當我們使用 TypeScript 時,我們想利用它提供的型別系統限制程式碼的方方面面,物件的鍵值,也不例外。
譬如我們有個物件儲存每個年級的人名,型別大概長這樣:
type Students = Record<string,string[]>;http://www.cppcns.com
理所當然地,資料就是長這樣:
const students: Students = { Freshman: ["David","John"],sophomore: [],Junior: ["Lily"],Senior: ["Tom"],};
限制物件鍵名為列舉
上面資料型別的問題是,年級是有限的幾種可值取,而該物件上可任意新增屬性,這樣顯得資料不夠純粹。
所以我們新增列舉,列出可取的值:
export enum Grade { Freshman,sophomore,Junior,Senior,}
現在,把物件的鍵名限制為上面列舉就行了。
- type Students = Record<string,string[]>; + type Students = Record<Grade,string[]>;
這樣我們的資料可寫成這樣:
const students: Students = {
[Grade.Freshman]: ["David",[Grade.sophomore]: [],[Grade.Junior]: ["Lily"],[Grade.Senio 程式設計客棧r]: ["Tom"],// ❌ Object literal may only specify known properties,and 'blah' does not exist in type 'Students'.ts(2322)
blah: ["some one"],};
這樣,限制住了物件身上鍵名的範圍,可以看到如果新增一個列舉之外的鍵會報錯。
更加語義化的列舉值
但上面的做法還是有不妥之處,因為列舉值預設是從 0 開程式設計客棧始的數字,這樣,作為鍵值就不夠語義了,這點從訪問物件的屬性時體現了出來:
修正我們的列舉,用更加語義的文字作為其值:
export enum Grade { Freshman = "Freshman",sophomore = "sophomore",Junior = "Junior",Senior = "Senior",}
此時再使用該列舉時,得到的就不是無意義的數字了。
如果你願意,列舉值也可以是中文,
export enum Grade { Freshman = "大一萌新",sophomore = "大二學弟",Junior = "大三學妹",Senior = "大四老司機",}
使用時也是沒任何問題的:
鍵值可選
上面的型別定義還有個問題,即,它要求使用時物件包含列舉中所有值,比如 sophomore
這個年級中並沒有人,可以不寫,但會報錯。
// ❌ 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",// [Grade.sophomore]: [],[Grade.Senior]: ["Tom"],};
所以,優化型別為可選:
type Students = Partial<Record<Grade,string[]>>;
假若可選的值不是通過列舉定義,而是來自一個數組,
constwww.cppcns.com grades = ["Freshman","sophomore","Junior","Senior"];
這意味著我們需要提取陣列中的值形成一個聯合型別。
首先利用const assertions 把陣列轉元組(Tuple)型別,
const grades = <const>["Freshman","Senior"];
再利用 typeof
和 Lookup Types 得到最終的聯合型別:
// 實際為 type Keys = "Freshman" | "sophomore" | "Junior" | "Senior" type Keys = typeof grades[number];
最後資料型別和資料可寫成:
type Students = Partial<Record<Keys,string[]>>; const students: Students = { Freshman: ["David","http://www.cppcns.comJohn"],};
須知這種形式下,物件的 key 與原陣列中元素其實沒有語法層面的關聯,即,編輯器的「跳轉定義」是不可用的。
儘量還是保持程式碼之間的關聯才能體現出 TypeScript 的作用,所以像這種只有型別約束而無法建立關聯的操作是不建議的。
相關資源
const assertions
keyof and Lookup Types
The text was updated successfully,but these errors were encountered:
以上就是TypeScript 中限制物件鍵名的取值範圍的詳細內容,更多關於TypeScript限制物件鍵名範圍的資料請關注我們其它相關文章!