1. 程式人生 > 程式設計 >TypeScript 中如何限制物件鍵名的取值範圍

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 開程式設計客棧始的數字,這樣,作為鍵值就不夠語義了,這點從訪問物件的屬性時體現了出來:

TypeScript 中如何限制物件鍵名的取值範圍

修正我們的列舉,用更加語義的文字作為其值:

export enum Grade {
  Freshman = "Freshman",sophomore = "sophomore",Junior = "Junior",Senior = "Senior",}

此時再使用該列舉時,得到的就不是無意義的數字了。

TypeScript 中如何限制物件鍵名的取值範圍

如果你願意,列舉值也可以是中文,

export enum Grade {
  Freshman = "大一萌新",sophomore = "大二學弟",Junior = "大三學妹",Senior = "大四老司機",}

使用時也是沒任何問題的:

TypeScript 中如何限制物件鍵名的取值範圍

鍵值可選

上面的型別定義還有個問題,即,它要求使用時物件包含列舉中所有值,比如 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 中如何限制物件鍵名的取值範圍

儘量還是保持程式碼之間的關聯才能體現出 TypeScript 的作用,所以像這種只有型別約束而無法建立關聯的操作是不建議的。

相關資源

const assertions

keyof and Lookup Types

The text was updated successfully,but these errors were encountered:

以上就是TypeScript 中限制物件鍵名的取值範圍的詳細內容,更多關於TypeScript限制物件鍵名範圍的資料請關注我們其它相關文章!