當我們使用 TypeScript 時,我們想利用它提供的型別系統限制程式碼的方方面面,物件的鍵值,也不例外。 譬如我們有個物件儲存每個年級的人名,型別大概長這樣: type Students = Record<string, string[]>;
理所當然地,資料就是長這樣: 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", "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"],
};
這樣,限制住了物件身上鍵名的範圍,可以看到如果新增一個列舉之外的鍵會報錯。 更加語義化的列舉值但上面的做法還是有不妥之處,因為列舉值預設是從 0 開始的數字,這樣,作為鍵值就不夠語義了,這點從訪問物件的屬性時體現了出來: 修正我們的列舉,用更加語義的文字作為其值: export enum Grade {
Freshman = "Freshman",
sophomore = "sophomore",
Junior = "Junior",
Senior = "Senior",
}
此時再使用該列舉時,得到的就不是無意義的數字了。 如果你願意,列舉值也可以是中文, export enum Grade {
Freshman = "大一萌新",
sophomore = "大二學弟",
Junior = "大三學妹",
Senior = "大四老司機",
}
使用時也是沒任何問題的: 鍵值可選上面的型別定義還有個問題,即,它要求使用時物件包含列舉中所有值,比如 // ❌ 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"],
};
所以,優化型別為可選: type Students = Partial<Record<Grade, string[]>>;
限制物件的鍵名為陣列中的值假若可選的值不是通過列舉定義,而是來自一個陣列, const grades = ["Freshman", "sophomore", "Junior", "Senior"];
這意味著我們需要提取陣列中的值形成一個聯合型別。 首先利用const assertions 把陣列轉元組(Tuple)型別, const grades = <const>["Freshman", "sophomore", "Junior", "Senior"];
再利用 // 實際為 type Keys = "Freshman" | "sophomore" | "Junior" | "Senior"
type Keys = typeof grades[number];
最後資料型別和資料可寫成: type Students = Partial<Record<Keys, string[]>>;
const students: Students = {
Freshman: ["David", "John"],
Junior: ["Lily"],
Senior: ["Tom"],
};
須知這種形式下,物件的 key 與原陣列中元素其實沒有語法層面的關聯,即,編輯器的「跳轉定義」是不可用的。 儘量還是保持程式碼之間的關聯才能體現出 TypeScript 的作用,所以像這種只有型別約束而無法建立關聯的操作是不建議的。 相關資源 |
The text was updated successfully, but these errors were encountered: |
TypeScript 中限制物件鍵名的取值範圍
相關文章
- MySQL欄位的取值範圍MySql
- MySQL中各種欄位的取值範圍(轉)MySql
- 列舉和列舉的取值範圍
- mysql中bigint、int、mediumint、smallint 和 tinyint的取值範圍MySql
- TypeScript中的範型TypeScript
- 保護範圍和物件物件
- 微控制器中的資料型別佔用空間及取值範圍資料型別
- Python限制輸入數字的範圍常用方法!Python
- 限制網址只能有指定範圍的字元組成字元
- SQL入門之8 限制插入資料的範圍SQL
- Java個人學習筆記-資料型別及取值範圍Java筆記資料型別
- C語言之有符號無符號整數取值範圍C語言符號
- Javascript解析之this代表物件及作用範圍JavaScript物件
- MySQL限制IP網段範圍從遠端訪問的方法MySql
- python date 和 datetime 的取值範圍(對比 Mysql 的 datetime 和 timestamp)PythonMySql
- Redis限制在規定時間範圍內登陸錯誤次數限制Redis
- TypeScript 2 : 獲取當前日期及前後範圍日期【Array】TypeScript
- typescript 中的 infer 關鍵字的理解TypeScript
- 專案範圍是專案成敗的關鍵(轉)
- request和response物件作用範圍不一樣麼?物件
- 02-Swift4 中 Private 的 使用範圍Swift
- CSS中background背景色的作用範圍CSS
- 聊聊TypeScript中列舉物件(Enum)TypeScript物件
- 專案範圍管理是專案成敗的關鍵 (轉)
- API關鍵詞介面的應用範圍說明API
- spring中的applicationContext的應用範圍SpringAPPContext
- wpf中DatePicker控制元件只能輸入年月,只能輸入年份,限制日期選擇範圍控制元件
- SAP ABAP Gateway 系統裡 HTTP 請求響應頭部欄位 DataServiceVersion 的可能取值範圍GatewayHTTP
- 【VPD】使用Oracle VPD(Virtual Private Database)限制使用者獲取資料的範圍OracleDatabase
- MongoDB的適用範圍MongoDB
- 公司公司程式碼業務範圍成本控制範圍概念
- 直播帶貨原始碼,日期時間選擇器 選擇範圍限制原始碼
- Js 比較兩個物件的鍵名與鍵值是否相等JS物件
- maven中scope依賴範圍與classpath的關係Maven
- 隨機範圍小數和隨機範圍整數隨機
- Java基本資料型別記憶體佔用位元組大小,取值範圍和預設值Java資料型別記憶體
- Javascript中變數範圍和hoist現象JavaScript變數
- 「Js」物件按照鍵名來進行排序JS物件排序