TypeScript 類型挑戰(zhàn):元組轉(zhuǎn)換為對象
高質(zhì)量的類型可以提高項目的可維護(hù)性并避免一些潛在的漏洞。
一些前端面試中考察到了 TypeScript 高級類型的定義,本系列主要解答來自 Type Challenges 項目中的 TS 類型挑戰(zhàn)問題,以此更好的了解 TS 的類型系統(tǒng),編寫自己的類型工具,更好的應(yīng)對前端面試。
下面來看一個難度為簡單的題目:元組轉(zhuǎn)換為對象
題目描述
傳入一個元組類型,將這個元組類型轉(zhuǎn)換為對象類型,這個對象類型的鍵/值都是從元組中遍歷出來。
例如:
const tuple = ['tesla', 'model 3', 'model X', 'model Y'] as const
type result = TupleToObject<typeof tuple>
// expected { tesla: 'tesla', 'model 3': 'model 3', 'model X': 'model X', 'model Y': 'model Y'}
題目解答
我們需要從數(shù)組中獲取所有值,并將其作為新對象中的鍵和值。
首先我們知道什么是元組,來看TypeScript 對元組的定義:
元組類型是另一種Array類型,它確切地知道包含多少個元素,以及它在特定位置包含哪些類型。
這意味著我們可以檢查length并得到確切的數(shù)字:
const fullName:[first: string, last: string] = ['hello', 'world'];
const range:[start: number, end: number] = [0, 10];
const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] as const;
type FullNameLength = (typeof fullName)['length'] // 2
type RangeLength = (typeof range)['length'] // 2
type DigitsLength = (typeof digits)['length'] // 10
而在數(shù)組中就無法實現(xiàn)這一點:
const fullName:string[] = ['hello', 'world'];
const range:number[] = [0, 10];
type FullNameLength = (typeof fullName)['length'] // number
type RangeLength = (typeof range)['length'] // number
可以使用映射類型來遍歷對象:
type MappedType<T> = {
[Key in keyof T]: T[Key];
};
- keyof T用于從對象類型T中獲取鍵值 key;
- in用于對對象鍵值key進(jìn)行迭代;
- Key 就是對象鍵值 key 本身;
- T[Key]是指定 Key 的值;
我們使用索引訪問類型來遍歷元組,可以通過T[number]從元組中獲取值。具體實現(xiàn)如下:
type TupleToObject<T> = {
[Value in T[number]]: Value;
};
- T[number] 用于從元組 T 中獲取值;
- in 用于迭代元組值;
- Value 是元組元素,用作構(gòu)建對象的key和value。
但是這時候報錯了:
這時就需要約束泛型的類型,最終的實現(xiàn)如下:
type TupleToObject<T extends readonly any[]> = {
[Value in T[number]]: Value;
};
這里的extends readonly any[] 是調(diào)用T[number] 所必須的,用來約束 T 的類型,T是一個元組,元組元素是只讀的。
Type Challenges:https://github.com/type-challenges/type-challenges