TS 手写Tuple to Object 学习类型体操( type-challenges ) 的第三天

182 阅读2分钟

今天学习的知识是 元组转换对象

废话不多说,直接上代码

要看明白该题需要以下知识点, 下面我会逐一分析所需要的知识

  • typeof
  • as const
  • 遍历数组

题目的链接 github.com/type-challe…

   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], {}]>

知识点分析

1 typeof

如果我们直接定义在 ts 的变量需要被使用,则可以使用 typeof

举个例子

     const tuple = ['tesla', 'model 3', 'model X', 'model Y'] 
     type a = tuple // 错误的写法
     //“tuple”表示值,但在此处用作类型。是否指“类型 tuple”?ts(2749)
     type a = typeof tuple  // 正确

Snipaste_2022-09-06_17-10-38.png

2 字面量类型

as const 将全部内容变成 const 类型

    const tuple = ['tesla', 'model 3', 'model X', 'model Y']
    type a = typeof tuple
    // as const 相对于下面的,但是需要经过typeof转换

    type aaaaaa = readonly ["tesla", "model 3", "model X", "model Y"] 
     // as const 将全部内容变成 const 类型

3 @ts-expect-error 期望下面的语句报错,下面没有报错我这个注释就报错

答案

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

这里需要用到 mapped 可以参考我上一篇所写的文章 juejin.cn/post/714015…

我们先来一行一行的分析

1 ( string | number | symbol)[] array 里面的值是不是 string | number | symbol 不是就报错

2 遍历一个数组

举个例子

    const tuple = ['tesla', 'model 3', 'model X', 'model Y'] as const
    
    type TupleToObject<T extends readonly ( string  | number | symbol)[]> = {
     [property in  T[number]]: property //下面写法一致
      [property in T[ 0 | 1| 2 | 3 ]]: property //从数组中取key
    }
    
    type aaaaaa = TupleToObject<typeof tuple>

因为前面使用了 extends 约束了类型,使用可以使用 in

方括号中的 in 关键字 表示我们正在处理映射类型。 或者说是在 联合类型中 遍历每一个成员

[property in T[ 0 ]]: property

Snipaste_2022-09-06_17-41-49.png