TypeScript 中常用的内置工具类型
TypeScript 中常用的内置工具类型:
一:操作接口类型
1. Partial:可以将类型的所有属性都变为可选
的
1.源码
type Partial<T> = {[P in keyof T]?: T[P];
}
- keyof T:通过类型索引 keyof 的得到联合类型 ‘name’ | ‘age’ | ‘weight’
- P in keyof T 等同于 p in ‘name’ | ‘age’ | ‘weight’,相当于执行了一次 forEach 的逻辑,遍历 ‘name’ | ‘age’ | ‘weight’
2.使用
// 定义一个通用的 Person 类
interface Person {name: string;age?: number;weight?: number;
}
type PartialPerson = Partial<Person>;// 相当于
interface PartialPerson {name?: string;age?: number;weight?: number;
}
2. Required:可以将类型的所有属性都变为必填
的(与 Partial 工具类型相反)
1.源码:映射类型在键值的后面使用了一个 - 符号,- 与 ? 组合起来表示去除类型的可选属性
,因此给定类型的所有属性都变为了必填。
type Required<T> = {[P in keyof T]-?: T[P];
};
2.使用
type RequiredPerson = Required<Person>;// 相当于
interface RequiredPerson {name: string;age: number;weight: number;
}
3.Readonly:可以将类型的所有属性设为只读
,这意味着属性不可以被重新赋值
1.源码
type Readonly<T> = {readonly [P in keyof T]: T[P];
};
2.使用
type ReadonlyPerson = Readonly<Person>;// 相当于
interface ReadonlyPerson {readonly name: string;readonly age?: number;readonly weight?: number;
}
4.Pick:可以从类型中选取出指定的键值,然后组成一个新的类型
1.源码:Pick工具类型接收了两个泛型参数:第一个 T 为给定的参数类型,而第二个参数为需要提取的键值 key。有了参数类型和需要提取的键值 key,我们就可以通过映射类型很容易地实现 Pick 工具类型的功能。
type Pick<T, K extends keyof T> = {[P in K]: T[P];
};
2.使用
type NewPerson = Pick<Person, 'name' | 'age'>;// 相当于
interface NewPerson {name: string;age?: number;
}
5.Omit:返回去除指定的键值之后返回的新类型(与 Pick 类型相反)
1.源码:
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
2.使用
type NewPerson = Omit<Person, 'weight'>;// 相当于
interface NewPerson {name: string;age?: number;
}
二:联合类型(可以通过|
将变量设置多种类型)
6.Exclude:从联合类型中去除指定的类型
1.源码:从 T 中剔除可以赋值给 U 的类型,如果 T 是 U 的子类型,则返回 never 不是则返回 T
type Exclude<T, U> = T extends U ? never : T
2.使用
type A = number | string | boolean
type B = number | booleantype Foo = Exclude<A, B>// 相当于
type Foo = string
7.Extract:从联合类型中提取指定的类型,类似于操作接口类型中的 Pick 类型(和Exclude相反)
1.源码
type Extract<T, U> = T extends U ? T : never;
2.使用
type A = number | string | boolean
type B = number | booleantype Foo = Extract<A, B>// 相当于
type Foo = number | boolean
8.NonNullable:从联合类型中去除 null 或者 undefined 的类型
1.源码
type NonNullable<T> = T extends null | undefined ? never : T;
2.使用
type T = NonNullable<string | number | undefined | null>; // => string | number
9.Record:生成接口类型,然后我们使用传入的泛型参数分别作为接口类型的属性和值
1.源码:接收了两个泛型参数:第一个参数作为接口类型的属性,第二个参数作为接口类型的属性值。
type Record<K extends keyof any, T> = {[P in K]: T;
};
2.使用
type MenuKey = 'home' | 'about' | 'more';
interface Menu {label: string;hidden?: boolean;
}
const menus: Record<MenuKey, Menu> = {about: { label: '关于' },home: { label: '主页' },more: { label: '更多', hidden: true },
};
三:函数类型
10.ConstructorParameters:可以用来获取构造函数的构造参数,而 ConstructorParameters 类型的实现则需要使用 infer 关键字推断构造参数的类型。
1.源码
type ConstructorParameters<T extends new (...args: any) => any> = T extends new (...args: infer P
) => any? P: never;
2.使用
class Person {constructor(name: string, age?: number) {}
}
type T = ConstructorParameters<typeof Person>; // [name: string, age?: number]
11.Parameters:可以用来获取函数的参数并返回序对
1.源码:以元组的方式获得函数的入参类型
type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;
2.使用
type T0 = Parameters<() => void>; // []
type T1 = Parameters<(x: number, y?: string) => void>; // [x: number, y?: string]
type T2 = Parameters<(name: string) => any>; // type T2 = [string]
type T3= Parameters<((name: string) => any) | ((age: number) => any)>; // type T3= [string] | [number]
12.ReturnType:用来获取函数的返回类型
1.源码
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;
2.使用
type T0 = ReturnType<() => void>; // => void
type T1 = ReturnType<() => string>; // => string
13.ThisParameterType:用来获取函数的 this 参数类型
1.源码
type ThisParameterType<T> = T extends (this: infer U, ...args: any[]) => any ? U : unknown;
2.使用
type T = ThisParameterType<(this: Number, x: number) => void>; // Number
14.ThisType:可以在对象字面量中指定 this 的类型
1.源码
type ObjectDescriptor<D, M> = {data?: D;methods?: M & ThisType<D & M>; // methods 中 this 的类型是 D & M
};
2.使用
function makeObject<D, M>(desc: ObjectDescriptor<D, M>): D & M {let data: object = desc.data || {};let methods: object = desc.methods || {};return { ...data, ...methods } as D & M;
}
const obj = makeObject({data: { x: 0, y: 0 },methods: {moveBy(dx: number, dy: number) {this.x += dx; // this => D & Mthis.y += dy; // this => D & M},},
});
obj.x = 10;
obj.y = 20;
obj.moveBy(5, 5);
15.OmitThisParameter:用来去除函数类型中的 this 类型
1.源码
type OmitThisParameter<T> = unknown extends ThisParameterType<T>? T: T extends (...args: infer A) => infer R? (...args: A) => R: T;
2.使用
type T = OmitThisParameter<(this: Number, x: number) => string>; // (x: number) => string
四:字符串类型
16. Uppercase、Lowercase、Capitalize、Uncapitalize
1.源码
// 转换字符串字面量到大写字母
type Uppercase<S extends string> = intrinsic;
// 转换字符串字面量到小写字母
type Lowercase<S extends string> = intrinsic;
// 转换字符串字面量的第一个字母为大写字母
type Capitalize<S extends string> = intrinsic;
// 转换字符串字面量的第一个字母为小写字母
type Uncapitalize<S extends string> = intrinsic;
2.使用
type T0 = Uppercase<'Hello'>; // => 'HELLO'
type T1 = Lowercase<T0>; // => 'hello'
type T2 = Capitalize<T1>; // => 'Hello'
type T3 = Uncapitalize<T2>; // => 'hello'
TypeScript 官方工具类型
TS 里几个常用的内置工具类型(Record、Partial 、 Required 、 Readonly、 Pick 、 Exclude 、 Extract 、 Omit)的使用