「这是我参与2022首次更文挑战的第2天,活动详情查看:2022首次更文挑战」。
概述
在上篇文章# TypeScript 内置工具类型学习(一)中,介绍 了部分TypeScript的内置工具类型,剩下部分将在这篇文章介绍完毕。
Omit(排除类型中的部分属性)
Omit<T, K extends keyof any>根据传入的条件,来排除掉类型的部分属性,然后组成一个新的类型。
源代码:
/**
* Construct a type with the properties of T except for those in type K.
*/
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
含义为:从T类型中挑出在K类型中没有的属性,然后组成一个新的类型。
- 首先使用Exclude排除掉
T与K当中都有的属性,并返回结果 - 然后使用Pick从
T中挑选出符合返回结果的属性,组成新的类型
代码示例:
在线示例
interface User {
name: string,
age: number,
address: string,
}
/**
相当于:
type User1 = {
name: string;
age: number;
}
*/
type User1 = Omit<User, 'address'>;
const user: User1 = {
name: '金小钗',
age: 18,
// address 已被排除,添加会报错
address: '广州',
}
type User1 = Omit<User, 'address'>的转换过程:
-
Exclude<keyof User, 'address'>
keyof User结果为'name' | 'age' | 'address'- 排除掉属性
address,返回结果为'name' | 'age'
- 根据上一步的结果,则有
Pick<User, 'name' | 'age'>
返回结果为:
{
name: string;
age: number;
}
NonNullable(排除null | undefined类型)
NonNullable可以用来排除掉类型中的null 和undefined类型,然后返回新类型。
源代码:
/**
* Exclude null and undefined from T
*/
type NonNullable<T> = T extends null | undefined ? never : T;
- 这个比较好理解,就是判断是否可以转换为
null | undefined类型,然后进行返回
代码示例:
在线示例
type T1 = 'a' | 'b' | null | undefined;
type T2 = NonNullable<T1>;
const a: T1 = null;
const b: T1 = undefined;
// 以下代码报错,因为 null 和 undefined 类型已被去除
const c: T2 = null;
const d: T2 = undefined;
Parameters(使用函数形参创建元组)
Parameters用于推断一个函数类型的形参类型,然后组合成一个有有名称的元组类型。
源代码:
/**
* Obtain the parameters of a function type in a tuple
*/
type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;
- 首先
T有约束条件,得为一个函数类型 - 在实际使用的时候,使用
infer推断参数的类型并赋值给Pinfer需要跟extends配合使用
- 返回的
P类型是个有名称的元组
代码示例:
在线示例
interface User {
name: string,
age: number,
}
type Foo = (user: User) => void;
/**
最终结果:
type P = [user: User]
*/
type P = Parameters<Foo>;
const user = {
name: '金小钗',
age: 18,
}
const a: P = [user];
更多例子:
ReturnType(获取函数返回值类型)
ReturnType可以用来获取一个函数的返回值类型。
源代码:
/**
* Obtain the return type of a function type
*/
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;
- 首先
T有约束条件,得是一个函数 - 在实际使用的时候,使用
infer推断返回值的类型并赋值给Rinfer需要跟extends配合使用
- 如果返回值类型推断不出来则会返回
any
代码示例:
在线示例
interface User {
name: string;
age: number;
}
type Foo = () => User;
/**
* 相当于:
* type T = User;
*/
type T = ReturnType<Foo>;
const user: T = {
name: '金小钗',
age: 233,
}
ConstructorParameters(使用构造函数形参创建元组)
ConstructorParameters用于推断一个类的构造函数的形参类型,然后组合成一个有有名称的元组类型。
源代码:
/**
* Obtain the parameters of a constructor function type in a tuple
*/
type ConstructorParameters<T extends abstract new (...args: any) => any> = T extends abstract new (...args: infer P) => any ? P : never;
- 首先
T有约束条件,得有一个构造函数 - 在实际使用的时候,使用
infer推断参数的类型并赋值给Pinfer需要跟extends配合使用
- 返回的
P类型是个有名称的元组
代码示例:
在线示例
// interface User {
// new(): User;
// name: string;
// age: number;
// }
class User {
private name: string;
private age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
// type T = ConstructorParameters<User>;
type T = ConstructorParameters<typeof User>;
const user: T = ['金小钗', 18];
很多知识我也还在学习中,更多详细信息请看下其他文章。
InstanceType(获取构造函数返回值类型)
InstanceType可以用来获取一个类的构造函数的返回值类型。
源代码:
/**
* Obtain the return type of a constructor function type
*/
type InstanceType<T extends abstract new (...args: any) => any> = T extends abstract new (...args: any) => infer R ? R : any;
- 首先
T有约束条件,得是一个构造函数 - 在实际使用的时候,使用
infer推断返回值的类型并赋值给Rinfer需要跟extends配合使用
- 如果返回值类型推断不出来则会返回
any
代码示例:
在线示例
interface UserConstrutor {
new(): User;
}
interface User {
name: string;
age: number;
}
/**
* 相当于:
* type T1 = User;
*/
type T1 = InstanceType<UserConstrutor>;
const user: T1 = {
name: '金小钗',
age: 233,
};
type T2 = InstanceType<ErrorConstructor>;
const error: T2 = {
name: 'err',
message: '错误',
}
ThisType(绑定上下文this)
ThisType是用在字面量对象中的,可以给其中定义的函数绑定上下文对象this。
源码:
/**
* Marker for contextual 'this' type
*/
interface ThisType<T> { }
- 使用时需要开启编译配置
noImplicitThis: true,否则使用this时没有智能提示功能
ThisType的实现就是个空的接口,只有在字面量对象类型中可以起到标示作用,否则直接使用也不会返回什么新的类型。
type T1 = ThisType<string>;
const a: T1 = '123';
const b: T1 = 1;
const c: T1 = { name: '金小钗' };
在上面代码中,虽然不会报错,但是变量使用起来就跟any类型一样。
代码示例:
type ObjectDescriptor<D, M> = {
data?: D;
// this 的类型为联合类型,就是 data 与 methods 对象
methods?: M & ThisType<D & M>; // Type of 'this' in methods is D & M
};
function makeObject<D, M>(desc: ObjectDescriptor<D, M>): D & M {
const data: object = desc.data || {};
const methods: object = desc.methods || {};
return { ...data, ...methods } as D & M;
}
const obj = makeObject({
data: { x: 1, y: 2 },
methods: {
moveBy(dx: number, dy: number) {
// 这里的 this 是有类型的
this.x += dx; // Strongly typed this
this.y += dy; // Strongly typed this
},
},
});
obj.x = 10;
obj.y = 20;
obj.moveBy(5, 5);
- 在
makeObject函数中,使用ObjectDescriptor限定参数的类型D和M用来推断实际的传入数据的类型- 在属性
methods的定义中,使用了ThisType来标识了的函数中this的类型,这样就可以确保this是有明确的类型的
所以直接在makeObject函数中使用字面量的方式定义desc对象时,就会有类型限制和智能代码提示了。
this的类型:
代码提示:
内置字符串操作类型
主要是针对内容为英文字母的操作
Uppercase(转换为大写)
Uppercase可以将字符串类型转换为大写的。
源码:
/**
* Convert string literal type to uppercase
*/
type Uppercase<S extends string> = intrinsic;
intrinsic代表功能由TS内部实现。
示例代码:
/**
* 相当于:
* type T1 = 'ABC';
*/
type T1 = Uppercase<'abc'>
const str: T1 = 'ABC';
Lowercase(转换为小写)
Lowercase可以将字符串类型转换为小写的。
源码:
/**
* Convert string literal type to lowercase
*/
type Lowercase<S extends string> = intrinsic;
intrinsic代表功能由TS内部实现。
示例代码:
/**
* 相当于:
* type T1 = 'abc';
*/
type T1 = Lowercase<'ABC'>
const str: T1 = 'abc';
Capitalize(首字母转换为大写)
Capitalize可以将字符串类型的首字母转换成大写的。
源码:
/**
* Convert first character of string literal type to uppercase
*/
type Capitalize<S extends string> = intrinsic;
intrinsic代表功能由TS内部实现。
示例代码:
/**
* 相当于:
* type T1 = 'Hello world';
*/
type T1 = Capitalize<'hello world'>
const str: T1 = 'Hello world';
Uncapitalize(首字母转换为小写)
Capitalize可以将字符串类型的首字母转换成小写的。
源码:
/**
* Convert first character of string literal type to lowercase
*/
type Uncapitalize<S extends string> = intrinsic;
intrinsic代表功能由TS内部实现。
示例代码:
/**
* 相当于:
* type T1 = 'hello World';
*/
type T1 = Uncapitalize<'Hello World'>
const str: T1 = 'hello World';