- Published on
Typescript 高级类型二
- Authors
- Name
- LIZHI
- Required 将类型属性都变成必填
- Exclude 排除一个 联合类型 中指定的子类型
- Extract 提取指定的 联合类型 中指定的子类型
- Omit 排除接口中指定的属性
- NonNullable 过滤掉 联合类型 中的 null 和 undefined 类型
- Parameters 获取函数的全部参数类型,以 元组类型 返回
- ConstructorParameters 获取的是 构造函数 的全部参数
- ReturnType 接收函数声明,返回函数的返回值类型,如果多个类型则以 联合类型 方式返回
- InstanceType 获取 构造函数 的返回类型,如果是多个就以 联合类型 的方式返回
- ThisParameterType 获取函数中 this 的数据类型,如果没有则返回 unknown 类型
- OmitThisParameter 移除函数中的 this 数据类型
Required
/**
* Make all properties in T required
*/
type Required<T> = {
[P in keyof T]-?: T[P];
};
与 Partial 程序类型的作用相反,将类型属性都变成必填。
type Coord = Required<{ x: number, y?:number }>;
// 等同于
type Coord = {
x: number;
y: number;
}
Exclude
/**
* 从 T 中排除那些可分配给 U 的类型
*/
type Exclude<T, U> = T extends U ? never : T;
排除一个 联合类型 中指定的子类型:
type T0 = Exclude<'a' | 'b' | 'c', 'b'> // 'a' | 'c'
type T1 = Exclude<string | number | boolean, boolean> // string | number
主要是基于 extends 条件类型的解析推迟的特性,返回了匹配之外的所有 候选类型,配合 never 类型 的空值特性,实现了这一高级类型。
Extract
/**
* 从 T 中提取可分配给 U 的类型
*/
type Extract<T, U> = T extends U ? T : never;
与 Exclude 完全相反的功能,用于提取指定的 联合类型,如果不存在提取类型,则返回never。可以用在判断一个复杂的 联合类型 中是否包含指定子类型:
type T0 = Extract<'a' | 'b' | 'c', 'a'> // 'a'
type T1 = Extract<string | number | boolean, boolean> // boolean
Omit
/**
* 构造一个具有 T 属性(类型 K 中的属性除外)的类型。
*/
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
这个在高级类型的使用频率也比较高。
排除接口中指定的属性:
interface I1 {
a: number;
b: string;
c: boolean;
}
type AC = Omit<I1, 'b'>; // { a:number; c:boolean }
type C = Omit<I1, 'a' |'b'> // { c: boolean }
NonNullable
/**
* Exclude null and undefined from T
*/
type NonNullable<T> = T extends null | undefined ? never : T;
过滤掉 联合类型 中的 null 和 undefined 类型:
type T1 = NonNullable<string | null | undefined>; // string
额外说明下,因为 null 和 undefined 类型的特殊性,他们可以赋值给任何类型,这往往会带来意料之外的错误。当你开启 --strictNullChecks 设置后,TS 就会严格检查,只有被声明 null 后才能被赋值:
// 关闭 --strictNullChecks
let s: string = "foo";
s = null; // 正常
// 开启 --strictNullChecks
s = null; // Error: Type 'null' is not assignable to type 'string'.
Parameters
/**
* 获取元组中函数类型的参数
*/
type Parameters<T extends (...args: any) => any> =
T extends (...args: infer P) => any ? P : never;
获取函数的全部参数类型,以 元组类型 返回:
type F1 = (a: string, b: number) => void;
type F1ParamTypes = Parameters(F1); // [string, number]
ConstructorParameters
/**
* 以元组结构返回构造函数类型的参数
*/
type ConstructorParameters<T extends new (...args: any) => any> =
T extends new (...args: infer P) => any ? P : never;
同上面的类型很相似,只是这里获取的是 构造函数 的全部参数。关于构造函数声明,以及如何使用此 高级类型 的方式:
interface IEntity {
count?: () => number
}
interface IEntityConstructor {
new (a: boolean, b: string): IEntity;
}
class Entity implements IEntity {
constructor(a: boolean, b: string) { }
}
type EntityConstructorParamType = ConstructorParameters<IEntityConstructor>; // [boolean, string]
这里的 IEntityConstructor 接口用来干什么的呢,当基于 创建实例函数 时就派上了用场:
function createEntity(ctor: IEntityConstructor, ...arg: EntityConstructorParamType): IEntity {
return new ctor(...arg);
}
const entity = createEntity(Entity, true, 'a');
ReturnType
/**
* 获取函数类型的返回类型
*/
type ReturnType<T extends (...args: any) => any> =
T extends (...args: any) => infer R ? R : any;
接收函数声明,返回函数的返回值类型,如果多个类型则以 联合类型 方式返回
type F1 = () => Date;
type F1ReturnType = ReturnType<F1>; // Date
InstanceType
/**
* 获取构造函数类型的返回类型
*/
type InstanceType<T extends new (...args: any) => any> =
T extends new (...args: any) => infer R ? R : any;
获取 构造函数 的返回类型,如果是多个就以 联合类型 的方式返回,我们借用上面的定义:
type EntityType = InstanceType<IEntityConstructor>; // IEntity
ThisParameterType
/**
* 提取函数类型的“this”参数的类型,如果函数类型没有“this”参数,则提取“未知”。
*/
type ThisParameterType<T> = T extends (this: infer U, ...args: any[]) => any ? U : unknown;
获取函数中 this 的数据类型,如果没有则返回 unknown 类型:
interface Foo {
x: number
};
function fn(this: Foo) {}
type Test = ThisParameterType<typeof fn>; // Foo
因为可以在 TS 声明函数的 this ,此方法用于获取此声明,具体的使用:
fn.bind({ x: 1 });
// 正常
fn.bind({ x: '1' });
// Error: ...Type 'string' is not assignable to type 'number'...
OmitThisParameter
/**
* Removes the 'this' parameter from a function type.
*/
type OmitThisParameter<T> = unknown extends ThisParameterType<T> ?
T : T extends (...args: infer A) => infer R ? (...args: A) => R : T;
移除函数中的 this 数据类型:
interface Foo {
x: number
};
type Fn = (this: Foo) => void
type NonReturnFn = OmitThisParameter<Fn>; // () => void
声明此类的函数类型效果如下:
function f(this: void) {} // 此声明在函数内不可使用 this