实现一个通用First<T>,它接受一个数组T并返回它的第一个元素的类型。

如果是空数组(也就是never[])返回never,其他数组返回第一元素的类型

  1. type First<T extends any[]> = T extends never[] ? never : T[0]
  2. type cases = [
  3. Expect<Equal<First<[3, 2, 1]>, 3>>,
  4. Expect<Equal<First<[() => 123, { a: string }]>, () => 123>>,
  5. Expect<Equal<First<[]>, never>>,
  6. Expect<Equal<First<[undefined]>, undefined>>
  7. ]

获取元组长度

创建一个通用的Length,接受一个readonly的数组,返回这个数组的长度。

接受一个 readonly 数组,必需在泛型传入时约束,否则 test case 过不了

  1. type Length<T extends readonly unknown[]> = T['length']
  2. /* _____________ 测试用例 _____________ */
  3. import { Equal, Expect } from '@type-challenges/utils'
  4. const tesla = ['tesla', 'model 3', 'model X', 'model Y'] as const
  5. const spaceX = ['FALCON 9', 'FALCON HEAVY', 'DRAGON', 'STARSHIP', 'HUMAN SPACEFLIGHT'] as const
  6. type cases = [
  7. Expect<Equal<Length<typeof tesla>, 4>>,
  8. Expect<Equal<Length<typeof spaceX>, 5>>,
  9. // @ts-expect-error
  10. Length<5>,
  11. // @ts-expect-error
  12. Length<'hello world'>,
  13. ]

如果不是上面的 test case 的话

  1. type Length<T extends any> = T extends readonly any[] ? T['length'] : never

Exclude

实现内置的Exclude
从T中排除可分配给U的那些类型

T为联合类型的时候,会进行拆分 比如 “a” | “b” | “c”, “a” 会拆分为 a extends a,b extends a,c extends a

  1. type MyExclude<T, U> = T extends U ? never : T
  2. /* _____________ 测试用例 _____________ */
  3. import { Equal, Expect } from '@type-challenges/utils'
  4. type cases = [
  5. Expect<Equal<MyExclude<"a" | "b" | "c", "a">, Exclude<"a" | "b" | "c", "a">>>,
  6. Expect<Equal<MyExclude<"a" | "b" | "c", "a" | "b">, Exclude<"a" | "b" | "c", "a" | "b">>>,
  7. Expect<Equal<MyExclude<string | number | (() => void), Function>, Exclude<string | number | (() => void), Function>>>,
  8. ]

Awaited

假如我们有一个 Promise 对象,这个 Promise 对象会返回一个类型。在 TS 中,我们用 Promise 中的 T 来描述这个 Promise 返回的类型。请你实现一个类型,可以获取这个类型。
比如:Promise<ExampleType>,请你返回 ExampleType 类型。

  1. /* _____________ 你的代码 _____________ */
  2. type Awaited<S extends unknown> = S extends Promise<infer Y > ? Y : S
  3. type MyAwaited<T extends Promise<unknown>> = T extends Promise<infer U> ? Awaited<U> : T
  4. /* _____________ 测试用例 _____________ */
  5. import type { Equal, Expect } from '@type-challenges/utils'
  6. type X = Promise<string>
  7. type Y = Promise<{ field: number }>
  8. type Z = Promise<Promise<string | number>>
  9. type cases = [
  10. Expect<Equal<MyAwaited<X>, string>>,
  11. Expect<Equal<MyAwaited<Y>, { field: number }>>,
  12. Expect<Equal<MyAwaited<Z>, string | number>>,
  13. ]
  14. // @ts-expect-error

If

Implement a utils If which accepts condition C, a truthy return type T, and a falsy return type F. C is expected to be either true or false while T and F can be any type.

For example:

  1. type A = If<true, 'a', 'b'> // expected to be 'a'
  2. type B = If<false, 'a', 'b'> // expected to be 'b'

solutions:

  1. type If<T, U, R> = T extends boolean ? ( T extends true ? U : R ) : never
  2. /* _____________ Test Cases _____________ */
  3. import { Equal, Expect } from '@type-challenges/utils'
  4. type cases = [
  5. Expect<Equal<If<true, 'a', 'b'>, 'a'>>,
  6. Expect<Equal<If<false, 'a', 2>, 2>>,
  7. ]
  8. // @ts-expect-error
  9. type error = If<null, 'a', 'b'>
  1. type Concat<T extends unknown[], U extends unknown[]> = [...T,...U]
  2. type a = Concat<[], []>
  3. type b = Concat<[], [1]>
  4. type c = Concat<[1, 2], [3, 4]>
  5. type d = Concat<['1', 2, '3'], [false, boolean, '4']>
  1. type Required1<T> = {
  2. [P in keyof T]-?: T[P];
  3. };
  1. /* _____________ 你的代码 _____________ */
  2. type Includes<T extends readonly unknown[], U> = T extends [infer Head, ...infer Rest]
  3. ? Equal<Head, U> extends true ? true : Includes<Rest, U>
  4. : false
  5. /* _____________ 测试用例 _____________ */
  6. import type { Equal, Expect } from '@type-challenges/utils'
  7. type cases = [
  8. Expect<Equal<Includes<['Kars', 'Esidisi', 'Wamuu', 'Santana'], 'Kars'>, true>>,
  9. Expect<Equal<Includes<['Kars', 'Esidisi', 'Wamuu', 'Santana'], 'Dio'>, false>>,
  10. Expect<Equal<Includes<[1, 2, 3, 5, 6, 7], 7>, true>>,
  11. Expect<Equal<Includes<[1, 2, 3, 5, 6, 7], 4>, false>>,
  12. Expect<Equal<Includes<[1, 2, 3], 2>, true>>,
  13. Expect<Equal<Includes<[1, 2, 3], 1>, true>>,
  14. Expect<Equal<Includes<[{}], { a: 'A' }>, false>>,
  15. Expect<Equal<Includes<[boolean, 2, 3, 5, 6, 7], false>, false>>,
  16. Expect<Equal<Includes<[true, 2, 3, 5, 6, 7], boolean>, false>>,
  17. Expect<Equal<Includes<[false, 2, 3, 5, 6, 7], false>, true>>,
  18. Expect<Equal<Includes<[{ a: 'A' }], { readonly a: 'A' }>, false>>,
  19. Expect<Equal<Includes<[{ readonly a: 'A' }], { a: 'A' }>, false>>,
  20. Expect<Equal<Includes<[1], 1 | 2>, false>>,
  21. Expect<Equal<Includes<[1 | 2], 1>, false>>,
  22. Expect<Equal<Includes<[null], undefined>, false>>,
  23. Expect<Equal<Includes<[undefined], null>, false>>,
  24. ]
  1. type MyOmit<T, K extends keyof T> = { [P in keyof T as P extends K ? never : P]: T[P] }
  1. /* _____________ 你的代码 _____________ */
  2. type Last<T extends any[]> = [any , ...T][T['length']]
  3. /* _____________ 测试用例 _____________ */
  4. import type { Equal, Expect } from '@type-challenges/utils'
  5. type cases = [
  6. Expect<Equal<Last<[3, 2, 1]>, 1>>,
  7. Expect<Equal<Last<[() => 123, { a: string }]>, { a: string }>>,
  8. ]