ts类型挑战【六】

102 阅读2分钟

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

题目七:awaited

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

type X = Promise<string>
type Y = Promise<{ field: number }>
type Z = Promise<Promise<string | number>>

type cases = [
  Expect<Equal<MyAwaited<X>, string>>,
  Expect<Equal<MyAwaited<Y>, { field: number }>>,
  Expect<Equal<MyAwaited<Z>, string | number>>,
]

// @ts-expect-error
type error = MyAwaited<number>

通过测试代码我们可以知道,MyAwaited 接收一个 Promise 类型的参数,返回 Promise 类型参数内的参数。

并且 Promise 类型内还可以嵌套另外一个 Promise,我们最终需要返回的是最里面的普通类型

接下来,来实现我们的代码:

  • 首先,我们知道 MyAwaited 接收的是一个 Promise
type MyAwaited<T extends Promise<any>> = any
  • 我们需要返回 Promise 内的类型(仅条件类型的 "extends" 子句中才允许 "infer" 声明。)
type MyAwaited<T extends Promise<any>> = T extends Promise<infer P> ? P : T

此时,我们就返回 Promise 内部的类型 P 了。

  • Promise 嵌套问题

如果传入的参数 Promise 内部还嵌套了 Promise 的话,此时的 P 就依然还是一个 Promise

type MyAwaited<T extends Promise<any>> = T extends Promise<infer P> 
	? P extends Promise<any>
		? MyAwaited<P>
		: P
	: T

题目八:if

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

type cases = [
  Expect<Equal<If<true, 'a', 'b'>, 'a'>>,
  Expect<Equal<If<false, 'a', 2>, 2>>,
]

// @ts-expect-error
type error = If<null, 'a', 'b'>

根据测试代码可以知道,If 接收三个参数,并根据第一个参数是 true 还是 false 来确定是返回第二个参数还是第三个参数

  • 第一个参数明显是 boolean 类型
type If<C extends boolean, T, F> = any
  • 如果 Ctrue 的话,返回 T,否则返回 F
type If<C extends boolean, T, F> = C extends true ? T : F

题目九:concat

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

type cases = [
  Expect<Equal<Concat<[], []>, []>>,
  Expect<Equal<Concat<[], [1]>, [1]>>,
  Expect<Equal<Concat<[1, 2], [3, 4]>, [1, 2, 3, 4]>>,
  Expect<Equal<Concat<['1', 2, '3'], [false, boolean, '4']>, ['1', 2, '3', false, boolean, '4']>>,
]

观察测试用例:

  • Concat 接收两个参数,并且都是 any 类型的数组
  • 得到的结果是两个参数数组合并成的一个数组,并且顺序和参数传入顺序一致

限制参数传入类型

type Concat<T extends any[], U extends any[]> = any

合并数组

ts 类型的数组类型中,也可以使用类似 js扩展运算符

type Concat<T extends any[], U extends any[]> = [...T, ...U]