simplify the life

【type-challenges】元祖转换为对象

元祖转换为对象

链接

首先熟悉下 as const 的用法,在这里会将数组变成只读元祖

const tuple = ['tesla', 'model 3', 'model X', 'model Y'] as const // 等同于 tuple 定义为 readonly ["tesla", "model 3", "model X", "model Y"]

其次可以用 T[number] 拿到元祖的联合类型:

const tuple = ['tesla', 'model 3', 'model X', 'model Y'] as const
type keys = (typeof tuple)[number] // "tesla" | "model 3" | "model X" | "model Y"

剩下的就比较简单了:

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

const tuple = ['tesla', 'model 3', 'model X', 'model Y'] as const
type result = TupleToObject<typeof tuple>

但是还有个问题,题面上希望以下代码能抛错:

type error = TupleToObject<[[1, 2], {}]>

显然目前用 any 是不会抛错的,而 js 中对象的 key 只能是 string、number 或者 symbol 类型,所以可以进一步约束下:

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

而 ts 中 PropertyKey 就是 string | number | symbol

type TupleToObject<T extends readonly PropertyKey[]> = {
  [key in T[number]]: key
}

另外一个比较有趣的技巧是 keyof any 也同样可以获取以上结果:

type ObjectKeys = keyof any // string | number | symbol

posted on 2023-04-21 19:08  lessfish  阅读(71)  评论(0)    收藏  举报

导航