类型挑战

感谢

感谢 type-challenges (opens new window) 这个项目,在初步学习 TypeScript 后得到了良好的练习。

工具

该项目提供了一些基础的工具来帮助测试。

对错

type Expect<T extends true> = T
type ExpectTrue<T extends true> = T
type ExpectFalse<T extends false> = T
type IsTrue<T extends true> = T
type IsFalse<T extends true> = T
1
2
3
4
5

相等

type Equal<X, Y> =
  (<T>() => T extends X ? 1 : 2) extends
  (<T>() => T extends Y ? 1 : 2) ? true : false
type NotEqual<X, Y> = true extends Equal<X, Y> ? false : true
1
2
3
4

any

type IsAny<T> = 0 extends (1 & T) ? true : false
type NotAny<T> = true extends IsAny<T> ? false : true
1
2

其他

export type Debug<T> = { [K in keyof T]: T[K] }
export type MergeInsertions<T> =
  T extends object
    ? { [K in keyof T]: MergeInsertions<T[K]> }
    : T

export type Alike<X, Y> = Equal<MergeInsertions<X>, MergeInsertions<Y>>

export type ExpectExtends<VALUE, EXPECTED> = EXPECTED extends VALUE ? true : false
export type ExpectValidArgs<FUNC extends (...args: any[]) => any, ARGS extends any[]> = ARGS extends Parameters<FUNC>
  ? true
  : false

export type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never
1
2
3
4
5
6
7
8
9
10
11
12
13
14

练习

Hello World

import { Equal, Expect, NotAny } from '@type-challenges/utils'

type HelloWorld = string

type cases = [
  Expect<NotAny<HelloWorld>>,
  Expect<Equal<HelloWorld, string>>
]
1
2
3
4
5
6
7
8

Pick

import { Equal, Expect } from '@type-challenges/utils'

type MyPick<T, K> = any

interface Todo {
  title: string
  description: string
  completed: boolean
}

interface Expected1 {
  title: string
}

interface Expected2 {
  title: string
  completed: boolean
}

type cases = [
  Expect<Equal<Expected1, Pick<Todo, 'title'>>>,
  Expect<Equal<Expected2, Pick<Todo, 'title' | 'completed'>>>
]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

Readonly

import { Equal, Expect } from '@type-challenges/utils'

type MyReadonly<T> = {
  readonly [K in keyof T]: T[K]
}

interface Todo1 {
  title: string
  description: string
  completed: boolean
}

type cases = [
  Expect<Equal<MyReadonly<Todo1>, Readonly<Todo1>>>
]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

Tuple to Object

import { Equal, Expect } from '@type-challenges/utils'

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

const tuple = ['tesla', 'model 3', 'model X', 'model Y'] as const

type cases = [
  Expect<Equal<TupleToObject<typeof tuple>, { tesla: 'tesla'; 'model 3': 'model 3'; 'model X': 'model X'; 'model Y': 'model Y'}>>,
]
1
2
3
4
5
6
7
8
9
10
11

First of Array

import { Equal, Expect } from '@type-challenges/utils'

type First<T extends any[]> = T extends [] ? never : T[0]

type cases = [
  Expect<Equal<First<[3, 2, 1]>, 3>>,
  Expect<Equal<First<[() => 123, { a: string }]>, () => 123>>,
  Expect<Equal<First<[]>, never>>,
  Expect<Equal<First<[undefined]>, undefined>>
]
1
2
3
4
5
6
7
8
9
10

Length of Tuple

import { Equal, Expect } from '@type-challenges/utils'

type Length<T extends readonly any[]> = T['length']

const tesla = ['tesla', 'model 3', 'model X', 'model Y'] as const
const spaceX = ['FALCON 9', 'FALCON HEAVY', 'DRAGON', 'STARSHIP', 'HUMAN SPACEFLIGHT'] as const

type cases = [
  Expect<Equal<Length<typeof tesla>, 4>>,
  Expect<Equal<Length<typeof spaceX>, 5>>,
]
1
2
3
4
5
6
7
8
9
10
11

Exclude

import { Equal, Expect } from '@type-challenges/utils'

type MyExclude<T, U> = T extends U ? never : T

type cases = [
  Expect<Equal<MyExclude<'a' | 'b' | 'c', 'a'>, Exclude<'a' | 'b' | 'c', 'a'>>>,
  Expect<Equal<MyExclude<'a' | 'b' | 'c', 'a' | 'b'>, Exclude<'a' | 'b' | 'c', 'a' | 'b'>>>,
  Expect<Equal<MyExclude<string | number | (() => void), Function>, Exclude<string | number | (() => void), Function>>>,
]
1
2
3
4
5
6
7
8
9

Awaited

import { Equal, Expect } from '@type-challenges/utils'

type Awaited<T> = T extends Promise<infer R> ? R : never

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

type cases = [
  Expect<Equal<Awaited<X>, string>>,
  Expect<Equal<Awaited<Y>, { field: number }>>,
]
1
2
3
4
5
6
7
8
9
10
11

If

import { Equal, Expect } from '@type-challenges/utils'

type If<C extends boolean, T, F> = C extends true ? T : F

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'>
1
2
3
4
5
6
7
8
9
10
11

Concat

import { Equal, Expect } from '@type-challenges/utils'

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

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']>>,
]
1
2
3
4
5
6
7
8
9
10
最后更新时间: 1 年前