type-challenges:Tuple to Object

41 阅读1分钟

Tuple to Object

问题描述

将一个元组类型转换为对象类型,这个对象类型的键/值和元组中的元素对应。

例如:

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'}
// ============= Test Cases =============
import type { Equal, Expect } from './test-utils'const tuple = ['tesla', 'model 3', 'model X', 'model Y'] as const
const tupleNumber = [1, 2, 3, 4] as const
const sym1 = Symbol(1)
const sym2 = Symbol(2)
const tupleSymbol = [sym1, sym2] as const
const tupleMix = [1, '2', 3, '4', sym1] 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 tupleSymbol>, { [sym1]: typeof sym1; [sym2]: typeof sym2 }>>,
  Expect<Equal<TupleToObject<typeof tupleMix>, { 1: 1; '2': '2'; 3: 3; '4': '4'; [sym1]: typeof sym1 }>>
]
​
// @ts-expect-error
type error = TupleToObject<[[1, 2], {}]>
​
// ============= Your Code Here =============
// 答案
type TupleToObject<T extends readonly PropertyKey[]> = {
  [K in T[number]]: K
}
​

const tuple = ['tesla', 'model 3', 'model X', 'model Y'] as const 意味着 tuple 的类型将不再是字符串组成的元组类型,而是写死的当前字符串字面量类型,也就是说,如果一个类型为 typeof tuple 那么该类型为 readonly ["tesla", "model 3", "model X", "model Y"],比如 type readTuple=typeof tuple 那么 readTuple 的类型就是 readonly ["tesla", "model 3", "model X", "model Y"] ,理解了这一点之后,再看我们要实现的类型 TupleToObject 就是将只读的元组类型转为对象类型即可,这里的键名和键值都为其自身,T[number] 会循环当前元组类型中的字面量类型,最终的 TupleToObject<typeof tuple> 类型即为

{
    'tesla': 'tesla'
    'model 3': 'model 3'
    'model X': 'model X'
    'model Y': 'model Y'
}