「TS类型体操00011」元组转换为对象

295 阅读2分钟

题目

实现一个类型工具 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] 就不可修改了。

tsdemo.png

思路

类比 JavaScript

类比 JavaScript,就是实现一个函数:

这个函数接收一个数组,新建一个对象,遍历数组,把数组的每个元素依次设置成对象keyvalue,最后返回这个对象

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;
}