TypeScript类型体操挑战(十四)

101 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第3天,点击查看活动详情

中等

Shift

挑战要求

在线示例

type Shift<T extends any[]> = T extends [any, ...infer E] ? E : never;
  • 这个就比较简单啦,通过元组的 rest 元素,就可以获取到我们想要的值啦

Tuple to Nested Object

挑战要求

在线示例

type Nested<F, E, U> = F extends string ? { [P in F]: TupleToNestedObject<E, U> } : never

type TupleToNestedObject<T, U> = T extends [infer F, ...infer E] ? Nested<F, E, U> : U;
  • 我这里通过Nested来组装对象
    • 通过F extends string进行条件判断只是为了把F确认为string类型
    • 因为值是一个嵌套的过程,所以就是要遍历数组元素,递归调用,最后就能完成嵌套的效果

我这里把处理嵌套对象的逻辑拆分为了一个独立的类型,并且通过条件判断来将确认键的类型,显得有点复杂,在解答区,我看到了一个更加简洁的答案:

type TupleToNestedObject<T, U> = 
  T extends [infer F, ...infer R] 
  ? {
      [K in F & string]: TupleToNestedObject<R, U>
    }
  : U

上面代码中,使用了&运算符来解决了要将F变为可以作为键类型的问题,例如:

// T = 'a'
type T = 'a' & string;

// 这种情况下,是冲突的,会返回 never
type T1 = string & number;

Reverse

挑战要求

在线示例

type Reverse<T> = T extends [...infer F, infer E] ? [E, ...Reverse<F>] : T;
  • 首先利用元组的rest元素,可以很轻易得拿到最后一个元素,并把它放在数组的第一个位置
  • 之后对rest元素F进行迭代,反复调用Reverse,就可以完成啦

Flip Arguments

挑战要求

在线示例

type Reverse<T> = T extends [...infer F, infer E] ? [E, ...Reverse<F>] : T;

type FlipArguments<T> = T extends (...args: infer P) => infer R ? (...args: Reverse<P>) => R : T;
  • 通过条件类型判断加上infer就可以去推断出函数的参数与返回值类型
  • 目的是将函数参数反转,那么通过扩展运算符,可以收集到所有的函数参数,这时它已经是个数组,只要使用Reverse<T>进行转换即可

TypeScript是结构类型,不是名义类型,所以这个函数参数的名称是无关紧要的