ts - 元组转换为对象

471 阅读1分钟

传入一个元组类型,将这个元组类型 转换为 对象类型,这个对象类型的键/值 都是 从元组中 遍历出来的。

例如:

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

先用js的思路写一遍

const arr = ['tesla', 'model 3', 'model X', 'model Y']

const obj = {}
for (let k of arr) {
    obj[k] = k
}

console.log(obj)

知识点:

1、as const : const 断言,作用是使其所有东西变成只读。
比如说const tuple = ['tesla', 'model 3', 'model X', 'model Y'] 变成const tuple = ['tesla', 'model 3', 'model X', 'model Y'] as const 就变成 const tuple: readonly ["tesla", "model 3", "model X", "model Y"]

2、ts遍历数组写法 : 【in T[number]】

3、typeof 的作用 : 将js中的let const var变量转换成ts的type interface

4、例子中type error = TupleToObject<[[1, 2], {}]>为什么没有typeof关键字?这里的[[1, 2], {}]指的是类型t(写死的类型),而不是js里的值

解答:

type TupleToObject<T extends any[]> = {
    [k in T[number]]: k
}

1、这里为啥加readonly 类型“readonly ["tesla", "model 3", "model X", "model Y"]”不满足约束“any[]”。 类型 "readonly ["tesla", "model 3", "model X", "model Y"]" 为 "readonly",不能分配给可变类型 "any[]"。

因为const tuple = ['tesla', 'model 3', 'model X', 'model Y'] as const也就是typeof tuple>是readonly, 后边的{ tesla: 'tesla'; 'model 3': 'model 3'; 'model X': 'model X'; 'model Y': 'model Y' }这个是写死的也是readonly,

所以 type TupleToObject<>这里面的饿 T extends any[] 也要加上个readonly 才行。

接着就是ts中数组的循环 [k in T[number]]

至此,这道题就完成了。


但是,当我要提交答案的时候,发现有个地方报了错,标注了红色波浪线:

截屏2022-06-28下午2.54.02.png

// @ts-expect-error 这个注释的作用是:这个注释用来指示下一行代码预期应该包含错误,下一行代码的错误将不会被编译器报告。这在对类型进行预期失败的测试时很有用

解释一下为什么报错:

ts-expect-error 这个注释,需要我们去修改 TupleToObject的泛型限制,才不会出现错误提示。作为对象的key只能是number string 以及 symbol类型,所以,我们需要将原来的any[] 修改为 {number | string | symbol[]}

最终解答:

type TupleToObject<T extends (number | string | symbol)[]> = {
    [k in T[number]]: k
}