题目
实现一个类型工具 TupleToObject<T>,接收一个元组类型T,将这个元组类型转换为对象类型,这个对象类型的键/值都是从元组中遍历出来。
例如:
const tuple = ['tesla', 'model 3', 'model X'] as const
// expected { tesla: 'tesla', 'model 3': 'model 3', 'model X': 'model X'}
type result = TupleToObject<typeof tuple>
原题链接
as const
as const 将某个类型固定为一个字面量类型。
比如例子中的 tuple,如果没有加 as const,那么它的类型是 string[],声明后可以将tuple[i] 的值修改成任意的字符串。
而现在tuple 加了 as const,它的类型就变成了 readonly ['tesla', 'model 3', 'model X'],这是固定的,tuple[i] 就不可修改了。
思路
类比 JavaScript
类比 JavaScript,就是实现一个函数:
这个函数接收一个数组,新建一个对象,遍历数组,把数组的每个元素依次设置成对象的 key 和 value,最后返回这个对象。
function TupleToObject(array) {
const obj = {};
array.forEach(item => {
obj[item] = item;
});
return obj;
}
提取逻辑点
1. 返回一个对象
2. 遍历元组字面量
再把逻辑点翻译成 TS 即可。
翻译成 TypeScript
用 typescript 实现上述逻辑点如下。
返回一个对象
// 返回一个 {} 即可
type TupleToObject<T> = {};
遍历元组字面量类型
遍历行为在 TS 中通过 [] 实现,具体做法如 [P in K],但是其中 K 必须是 联合类型,如'a'|'b'|'c'。
然而,类型工具 TupleToObject 拿到的 T 是一个元组字面量类型,如 ['tesla', 'model 3', 'model X'],这如何遍历?
[P in T[number]]
要遍历元组字面量类型,需要通过 [P in T[number]] 这样特定的 typescript 语法。
[P in T[number]]
实现
综上所述,最终的类型工具 TupleToObject 实现为:
type TupleToObject<T extends readonly any[]> = {
[P in T[number]]: P;
}