TS
coderljw 2024-10-13 大约 3 分钟
# 1. 类型查看展开 (opens new window)
type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never
type ExpandRecursively<T> = T extends object
? T extends infer O
? { [K in keyof O]: ExpandRecursively<O[K]> }
: never
: T
1
2
3
4
5
6
7
2
3
4
5
6
7
# 2. Pick
type MyPick<T, K extends keyof T> = {
[P in K]: T[P]
}
1
2
3
2
3
- Example
interface Todo {
title: string
description: string
completed: boolean
}
type TodoPreview = MyPick<Todo, 'title' | 'completed'>
const todo: TodoPreview = {
title: 'Clean room',
completed: false,
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# 3. Readonly
type MyReadonly<T> = {
readonly [P in keyof T]: T[P]
}
1
2
3
2
3
- Example
interface Todo {
title: string
description: string
}
const todo: MyReadonly<Todo> = {
title: 'Hey',
description: 'foobar',
}
todo.title = 'Hello' // Error: cannot reassign a readonly property
todo.description = 'barFoo' // Error: cannot reassign a readonly property
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# 4. 元祖转换为对象
type TupleToObject<T extends readonly any[]> = {
[P in T[number]]: P
}
1
2
3
2
3
- Example
const tuple = ['tesla', 'model 3', 'model X', 'model Y'] as const
type result = TupleToObject<typeof tuple> // expected { tesla: 'tesla', 'model 3': 'model 3', 'model X': 'model X', 'model Y': 'model Y'}
1
2
3
2
3
# 5. 第一个元素
type First<T extends unknown[]> = T extends [infer R, ...infer Rest] ? R : never
1
- Example
type arr1 = ['a', 'b', 'c']
type arr2 = [3, 2, 1]
type head1 = First<arr1> // expected to be 'a'
type head2 = First<arr2> // expected to be 3
1
2
3
4
5
2
3
4
5
# 6. 获取元祖长度
type Length<T extends readonly unknown[]> = T['length']
1
- Example
type tesla = ['tesla', 'model 3', 'model X', 'model Y']
type spaceX = [
'FALCON 9',
'FALCON HEAVY',
'DRAGON',
'STARSHIP',
'HUMAN SPACEFLIGHT'
]
type teslaLength = Length<tesla> // expected 4
type spaceXLength = Length<spaceX> // expected 5
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 7. Exclude
type MyExclude<T, U> = T extends U ? never : T
1
- Example
type union = 'a' | 'b' | 'c'
type result = MyExclude<union, 'a'> // expected "b" | "c"
1
2
3
2
3
# 8. Awaited
type MyAwaited<T> = T extends Promise<infer R> ? MyAwaited<R> : T
1
- Example
type Z = Promise<Promise<string | number>>
type result = MyAwaited<Z> // expected string | number
1
2
3
2
3
# 9. If
type If<C, T, F> = C extends true ? T : F
1
- Example
type A = If<true, 'a', 'b'> // expected to be 'a'
type B = If<false, 'a', 'b'> // expected to be 'b'
1
2
2
# 10. Concat
type Concat<T extends unknown[], U extends unknown[]> = [...T, ...U]
1
- Example
type Result = Concat<[1], [2]> // expected to be [1, 2]
1
# 11. Includes
type IsEqual<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y
? 1
: 2
? true
: false
type Includes<T extends readonly any[], U> = T extends [infer F, ...infer R]
? IsEqual<F, U> extends true
? true
: Includes<R, U>
: false
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
- Example
type isPillarMen = Includes<['Kars', 'Esidisi', 'Wamuu', 'Santana'], 'Dio'> // expected to be `false`
1
# 12. Push
type Push<T extends unknown[], U> = [...T, U]
1
- Example
type Result = Push<[1, 2], '3'> // [1, 2, '3']
1
# 13. Unshift
type Unshift<T extends unknown[], U> = [U, ...T]
1
- Example
type Result = Unshift<[1, 2], 0> // [0, 1, 2,]
1
# 14. MyParameters
type MyParameters<T extends (...args: any[]) => any> = T extends (
...args: infer P
) => any
? P
: never
1
2
3
4
5
2
3
4
5
- Example
const foo = (arg1: string, arg2: number): void => {}
type result = MyParameters<typeof foo> // expected [arg1: string, arg2: number]
1
2
3
2
3
# 15. 获取函数返回类型
type MyReturnType<T extends (...args: any) => any> = T extends (
...args: any
) => infer R
? R
: any
1
2
3
4
5
2
3
4
5
- Example
const fn = (v: boolean) => {
if (v) return 1
else return 2
}
type a = MyReturnType<typeof fn> // expected "1 | 2"
1
2
3
4
5
6
2
3
4
5
6
# 16. 获取函数返回类型
type MyReturnType<T extends (...args: any) => any> = T extends (
...args: any
) => infer R
? R
: any
1
2
3
4
5
2
3
4
5
- Example
const fn = (v: boolean) => {
if (v) return 1
else return 2
}
type a = MyReturnType<typeof fn> // expected "1 | 2"
1
2
3
4
5
6
2
3
4
5
6
# 17. Omit
type MyOmit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>
1
- Example
interface Todo {
title: string
description: string
completed: boolean
}
type TodoPreview = MyOmit<Todo, 'description' | 'title'>
const todo: TodoPreview = {
completed: false,
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 18. Readonly 2
type MyReadonly2<T, K extends keyof T = keyof T> = {
readonly [P in keyof T]: T[P]
} & {
[P in Exclude<keyof T, K>]: T[P]
}
1
2
3
4
5
2
3
4
5
- Example
interface Todo {
title: string
description: string
completed: boolean
}
const todo: MyReadonly2<Todo, 'title' | 'description'> = {
title: 'Hey',
description: 'foobar',
completed: false,
}
todo.title = 'Hello' // Error: cannot reassign a readonly property
todo.description = 'barFoo' // Error: cannot reassign a readonly property
todo.completed = true // OK
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 19. 深度 Readonly
type DeepReadonly<T> = T extends Record<string, unknown> | Array<unknown>
? { readonly [k in keyof T]: DeepReadonly<T[k]> }
: T
1
2
3
2
3
- Example
type X = {
x: {
a: 1
b: 'hi'
}
y: 'hey'
}
type Expected = {
readonly x: {
readonly a: 1
readonly b: 'hi'
}
readonly y: 'hey'
}
type Todo = DeepReadonly<X> // should be same as `Expected`
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17