ts类型挑战【二十五】

121 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第27天,点击查看活动详情

题目四十四:tuple-to-nested-object

// template.ts
type TupleToNestedObject<T, U> = any
// test-cases.ts
import type { Equal, Expect } from '@type-challenges/utils'

type cases = [
  Expect<Equal<TupleToNestedObject<['a'], string>, { a: string }>>,
  Expect<Equal<TupleToNestedObject<['a', 'b'], number>, { a: { b: number } }>>,
  Expect<Equal<TupleToNestedObject<['a', 'b', 'c'], boolean>, { a: { b: { c: boolean } } }>>,
  Expect<Equal<TupleToNestedObject<[], boolean>, boolean>>,
]

给定一个只包含字符串类型的元组类型 T,以及一个类型 U,递归地构建一个对象。

代码实现

  • 原代码
type TupleToNestedObject<T, U> = any
  • T 继承自数组
type TupleToNestedObject<T extends any[], U> = any
  • 将数组解构(如果拆分不出来东西,按照题目要求返回第二个参数 U
type TupleToNestedObject<T extends any[], U> = T extends [infer First, ...infer Rest]
	? ...
	: U
  • 按照题目要求,最后会返回一个对象,这里使用 Record
type TupleToNestedObject<T extends any[], U> = T extends [infer First, ...infer Rest]
	? Record<..., ...>
	: U
  • Record 的第一个参数为 key,这里应该是数组中拆分出来的 FirstFirst不能单独作为 key,使用 & 符号转为 string
type TupleToNestedObject<T extends any[], U> = T extends [infer First, ...infer Rest]
	? Record<First & string, ...>
	: U
  • Record 的值为 TupleToNestedObject 的递归
type TupleToNestedObject<T extends any[], U> = T extends [infer First, ...infer Rest]
	? Record<First & string, TupleToNestedObject<Rest, U>>
	: U

题目四十五:reverse

// template.ts
type Reverse<T> = any
// test-cases.ts
import type { Equal, Expect } from '@type-challenges/utils'

type cases = [
  Expect<Equal<Reverse<['a', 'b']>, ['b', 'a']>>,
  Expect<Equal<Reverse<['a', 'b', 'c']>, ['c', 'b', 'a']>>,
]

实现 TS 版本的 Array.reverse

代码实现

  • 原代码
type Reverse<T> = any
  • T 是一个数组,再多设置一个 Result 在存放结果
type Reverse<T extends any[], Result extends any[] = []> = any
  • T 进行解构,如果解构不出来则直接返回 Result
type Reverse<T extends any[], Result extends any[] = []> = T extends [infer First, ...infer Rest]
	? ...
	: Result
  • 继续对剩余的内容(Rest)进行翻转
type Reverse<T extends any[], Result extends any[] = []> = T extends [infer First, ...infer Rest]
	? Reverse<Rest>
	: Result
  • 递归调用 Reverse 中的第二个参数(结果参数,将解构出来的 First加上)
type Reverse<T extends any[], Result extends any[] = []> = T extends [infer First, ...infer Rest]
	? Reverse<Rest, [First, ...Result]>
	: Result

注意

TS 这里不能直接对 T 中的内容进行翻转,需要借助另一个参数 Result 作为结果数组来进行操作