當我們使用 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
- 列舉和列舉的取值範圍
- 保護範圍和物件物件
- 微控制器中的資料型別佔用空間及取值範圍資料型別
- python date 和 datetime 的取值範圍(對比 Mysql 的 datetime 和 timestamp)PythonMySql
- TypeScript中的範型TypeScript
- Python限制輸入數字的範圍常用方法!Python
- Java個人學習筆記-資料型別及取值範圍Java筆記資料型別
- typescript 中的 infer 關鍵字的理解TypeScript
- 02-Swift4 中 Private 的 使用範圍Swift
- wpf中DatePicker控制元件只能輸入年月,只能輸入年份,限制日期選擇範圍控制元件
- SAP ABAP Gateway 系統裡 HTTP 請求響應頭部欄位 DataServiceVersion 的可能取值範圍GatewayHTTP
- 聊聊TypeScript中列舉物件(Enum)TypeScript物件
- Js 比較兩個物件的鍵名與鍵值是否相等JS物件
- API關鍵詞介面的應用範圍說明API
- 直播帶貨原始碼,日期時間選擇器 選擇範圍限制原始碼
- 「Js」物件按照鍵名來進行排序JS物件排序
- Java基本資料型別記憶體佔用位元組大小,取值範圍和預設值Java資料型別記憶體
- 範圍分割槽
- 軟考——範圍
- 隨機範圍小數和隨機範圍整數隨機
- TypeScript 中令人迷惑的物件型別:Object、{} 和 objectTypeScript物件型別Object
- Range範圍選區的理解
- 列舉範圍內的字串字串
- 關於SAP的MRP範圍
- JavaScript 限定範圍的拖拽效果JavaScript
- php去除陣列中的鍵名PHP陣列
- MATLAB中如何生成指定範圍的隨機整數向量Matlab隨機
- SciPy 應用範圍
- JavaScript 拖拽限定範圍JavaScript
- Map中取值toString()
- 「極速上手TypeScript」TypeScript進階“物件”TypeScript物件
- SonarQube系列-透過配置掃描分析範圍,聚焦關鍵問題
- Cookie 的特徵與範圍用例Cookie特徵
- 基礎 變數的作用範圍變數
- 不可變陣列的範圍求和陣列
- aspx中的checkbox 取值問題
- 提高SAR ADC精度的外圍電路RC元件取值公式推導元件公式