测试 case
import type { Equal, Expect } from '@type-challenges/utils'
const tuple = ['tesla', 'model 3', 'model X', 'model Y'] as const
const tupleNumber = [1, 2, 3, 4] as const
const tupleMix = [1, '2', 3, '4'] as const
type cases = [
Expect<Equal<TupleToObject<typeof tuple>, { tesla: 'tesla'; 'model 3': 'model 3'; 'model X': 'model X'; 'model Y': 'model Y' }>>,
Expect<Equal<TupleToObject<typeof tupleNumber>, { 1: 1; 2: 2; 3: 3; 4: 4 }>>,
Expect<Equal<TupleToObject<typeof tupleMix>, { 1: 1; '2': '2'; 3: 3; '4': '4' }>>,
]
// @ts-expect-error
type error = TupleToObject<[[1, 2], {}]>
- template.ts
type TupleToObject<T extends readonly any[]> = any
相关知识点
-
typeof
使用 let const 声明的 我们称之为 js 世界
使用 type interface 声明的可以成为 type 世界
typeof 可以把js世界的东西变成类型世界的东西,参与到类型世界里的计算 -
as const
将我们的类型变成写死的字面量类型
const tuple = ['tesla', 'model 3', 'model X', 'model Y']
type r = typeof tuple // string[]
tuple[0] ='xxx'
上面代码不加 as const 我们的 r是string[],因为我们可以对里面的每一项进行修改
const tuple = ['tesla', 'model 3', 'model X', 'model Y'] as const
type r = typeof tuple // readonly ["tesla", "model 3", "model X", "model Y"]
tuple[0] ='xxx' // 无法分配到 "0" ,因为它是只读属性
加上 as const 后我们的 r 就变成了只读的字面量类型了,而且里面的每一项都不可以修改都是一个常量
- T[number]
得到数组里的每一项的联合类型
const arr = [1,2,3] as const
type a = typeof arr[number] // 1 | 2 | 3
配合 in 可对齐每一项进行遍历
js 实现
const tupleToObject = (array) => {
const obj = {}
array.forEach((val) => {
obj[val] = val
})
return obj
}
步骤
- 返回一个对象
- 遍历array
ts 实现
// 1. = {}
// 2. [P in T[number]]
type TupleToObject<T extends readonly(string | number | symbol)[]> = {
[P in T[number]]: P
}
网友评论