# Utility Types
# 什么是Utility Types?
Utility Types是TypeScript的**工具类型方便开发者更好的约束类型**
# Partial<T>
将T中所有属性转换为可选属性。返回的类型可以是T的任意子集。
interface Todo {
title: string;
description: string;
done: boolean;
}
function updateTodo(todo: Todo, newTodo: Partial<Todo>) {
return { ...todo, ...newTodo };
}
const todo: Todo = {
title: 'First Todo',
description: 'this is the first todo',
done: false
};
updateTodo(todo, { done: true });
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
源码:
type Partial&#60;T&#62; = { [P in keyof T]?: T[P]; };
1
解析: keyof T, 索引类型查询操作符。 对于任何类型 T, keyof T 的结果为 T 上已知的公共属性名的联合。
type todoKeys = keyof Todo; // "title" | "description" | "done"
1
keyof 取到 T 中的属性名,in 操作符遍历属性名。可选属性操作符 ? 将所有属性定义为可选属性。
# Required<T>
通过将T的所有属性设置为必选属性来构造一个新的类型。与Partial相对。
interface Example {
a?: string;
b?: string;
}
const example1: Example = { a: 'aaa' }; // right
const example2: Required<Example> = { a: 'aaa' };
// error: Property 'b' is missing in type '{ a: string; }' but required in type 'Required<Example>'
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
源码:
type Required&#60;T&#62; = { [P in keyof T]-?: T[P]; };
// 与partial相似,遍历T中属性,并将所有属性置为必选属性
1
2
2
# Readonly<T>
将T中所有属性设置为只读
interface Todo {
title: string;
}
const todo: Readonly<Todo> = { title: 'First Todo' };
todo.title = 'New Title'; // Cannot assign to 'title' because it is a read-only property.
1
2
3
4
5
6
7
2
3
4
5
6
7
源码:
type Readonly&#60;T&#62; = { readonly [P in keyof T]: T[P]; };
1
# Record<K,T>
构造一个类型,该类型具有一组属性K,每个属性的类型为T。可用于将一个类型的属性映射为另一个类型。
type TodoProperty = 'title' | 'description';
type Todo = Record<TodoProperty, string>;
const todo: Todo = {
title: 'First Todo',
description: 'this is the first todo'
};
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
源码:
type Record<K extends keyof any, T> = { [P in K]: T; };
1
# Pick<T,K>
通过在T中抽取一组属性K构建一个新类型.
interface Todo {
title: string;
description: string;
done: boolean;
}
type TodoBase = Pick<Todo, 'title' | 'done'>;
const todo: TodoBase = {
title: 'First Todo',
done: false
};
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
源码:
type Pick<T, K extends keyof T> = { [p in K]: T[p] };// K是T的属性集合的子集
1
# Exclude<T,U>
从T中排除可分配给U的属性,剩余的属性构成新的类型
type T0 = Exclude<'a' | 'b' | 'c', 'a'>; // "b" | "c"
type T2 = Exclude<string | number | (() => void), Function>; // string | number
1
2
3
2
3
源码:
type Exclude<T, U> = T extends U ? never : T;
1
# Extract<T,U>
从T中抽出可分配给U的属性构成新的类型。与Exclude相反
type T0 = Extract<'a' | 'b' | 'c', 'a'>; // "a"
// 多参数类型约束
interface StringItem {
type: 'stringItem'
value: string;
}
interface NumberItem {
type: 'numberItem'
value: number;
}
type Item = StringItem | NumberItem;
function addCase<IType extends Item['type']>(type: IType, value: Extract<Item, { type: IType }>['value']): void {
console.log(type, ':', value);
}
addCase('stringItem', 'value1'); // right
addCase('numberItem', 2); // right
addCase('stringItem', 1); // error:类型“1”的参数不能赋给类型“string”的参数
addCase('numberItem', 'value2'); // error:类型“"value2"”的参数不能赋给类型“number”的参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
源码:
type Extract<T, U> = T extends U ? T : never;
1
# Omit<T,K>
从T中取出除去K的其他所有属性。与Pick相对。
interface Todo {
title: string;
description: string;
done: boolean;
}
type TodoBase = Omit<Todo, 'description'>;
const todo: TodoBase = {
title: 'First Todo',
done: false
};
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
源码:
// 结合Exclude和Pick实现
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
1
2
2
# NonNullable<T>
去除T中的 null 和 undefined 类型
type T0 = NonNullable<number | string | undefined> // number | string
type T1 = NonNullable<number | null | undefined> // number
1
2
3
2
3
源码:
type NonNullable&#60;T&#62; = T extends null | undefined ? never : T;
1
# Parameters<T>
返回类型为T的函数的参数类型所组成的数组
declare function f1(arg: { a: number, b: string }): void
type T0 = Parameters<() => string>; // []
type T1 = Parameters<(s: string) => void>; // [string]
type T2 = Parameters<(&#60;T&#62;(arg: T) => T)>; // [unknown]
type T4 = Parameters<typeof f1>; // [{ a: number, b: string }]
type T5 = Parameters<any>; // unknown[]
type T6 = Parameters<never>; // never
type T7 = Parameters<string>; // Error: 类型“string”不满足约束“(...args: any) => any”
type T8 = Parameters<Function>; // Error: 类型“Function”不满足约束“(...args: any) => any”。类型“Function”提供的内容与签名“(...args: any): any”不匹配
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
源码:
type ConstructorParameters<T extends new (...args: any) => any> = T extends new (...args: infer P) => any ? P : never;
1
解析:
条件类型中的类型推断(高级类型章节)(原文档截图):
翻译:
在条件类型中使用extends时,可以声明一个infer来表示有一个类型变量需要推断。这个可推断的类型变量可以在条件类型的true分支上引用。同一个类型变量可能有多个推断的位置。
type Foo&#60;T&#62; = T extends { a: infer U, b: infer U } ? U : never;
type T10 = Foo<{ a: string, b: string }>; // string
type T11 = Foo<{ a: string, b: number }>; // string | number
1
2
3
4
5
2
3
4
5
# ReturnType<T>
function T的返回类型
declare function f1(): { a: number, b: string }
type T0 = ReturnType<() => string>; // string
type T1 = ReturnType<(s: string) => void>; // void
type T2 = ReturnType<(&#60;T&#62;() => T)>; // {}
type T3 = ReturnType<(<T extends U, U extends number[]>() => T)>; // number[]
type T4 = ReturnType<typeof f1>; // { a: number, b: string }
type T5 = ReturnType<any>; // any
type T6 = ReturnType<never>; // any
type T7 = ReturnType<string>; // Error: 类型“string”不满足约束“(...args: any) => any”
type T8 = ReturnType<Function>; // Error:类型“Function”不满足约束“(...args: any) => any”。类型“Function”提供的内容与签名“(...args: any): any”不匹配
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
源码:
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;
1
# InstanceType<T>
返回构造函数类型T的实例类型
class C {
x = 0;
y = 0;
}
type T0 = InstanceType<typeof C>; // C
type T1 = InstanceType<any>; // any
type T2 = InstanceType<never>; // any
type T3 = InstanceType<string>; // error:类型“string”不满足约束“new (...args: any) => any”
type T4 = InstanceType<Function>; // error:类型“Function”不满足约束“new (...args: any) => any”。类型“Function”提供的内容与签名“new (...args: any): any”不匹配
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
源码:
type InstanceType<T extends new (...args: any) => any> = T extends new (...args: any) => infer R ? R : any;
1