随着 Typescript 的普及,越来越多的前端项目开始使用 Typescript,做了几个项目后发现自己对 Typescript 内置类型非常不熟悉,今天梳理下知识点介绍下 Typescript 内置工具类型和常用操作符
Partial<Type>
Required<Type>
Readonly<Type>
Record<Keys, Type>
Pick<Type, Keys>
Omit<Type, Keys>
Exclude<UnionType, ExcludedMembers>
Extract<Type, Union>
NonNullable<Type>
Parameters<Type>
ConstructorParameters<Type>
ReturnType<Type>
InstanceType<Type>
Uppercase<StringType>
Lowercase<StringType>
Capitalize<StringType>
Uncapitalize<StringType>
内置工具类型 Utility Types
Partial(部分的)
作用是将传入的属性变为可选项
实现原理
/**
* Make all properties in T optional
*/
type Partial<T> = {
[P in keyof T]?: T[P];
};
Example
interface Foo {
name: string;
age: number;
}
type B = Partial<Foo>;
//type B = {name?: string; age?: number;}
Required(必须的)
作用是将传入的属性变为必选项
实现原理
/**
* Make all properties in T required
*/
type Required<T> = {
[P in keyof T]-?: T[P];
};
Example
interface Foo {
name?: string;
age?: number;
}
type A = Required<Foo>;
// type A = {name: string; age: number;}
Readonly(只读的)
作用是让传入类型中的所有属性变成都是只读的(不能修改属性)
实现原理
/**
* Make all properties in T readonly
*/
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
Example
interface Todo {
title: string;
}
const todo: Readonly<Todo> = {
title: "Delete inactive users",
};
todo.title = "Hello"; //Cannot assign to 'title' because it is a read-only property.
Record(记录)
作用是构建一个类型,这个类型用来描述一个对象,这个对象的属性都具有相同的类型
实现原理
/**
* Construct a type with a set of properties K of type T
*/
type Record<K extends keyof any, T> = {
[P in K]: T;
};
Example
export const student1: Record<string, any> = {
name: "张三",
age: 20,
};
Pick(摘取)
作用是选择传入类型中的部分属性组成新类型
实现原理
/**
* From T, pick a set of properties whose keys are in the union K
*/
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
Example
interface User {
age: number;
name: string;
type: boolean;
}
type PickUser = Pick<User, "age" | "name">;
//type PickUser = { age: number; name: string; }
Omit(省略)
传入一个类型,和这个类型的几个属性,把传入的属性省略掉,组成一个新类型
实现原理
/**
* 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>>;
Example
interface User {
id: number;
age: number;
name: string;
}
type OmitUser = Omit<User, "id">;
// type OmitUser = { age: number; name: string; }
Exclude(排除)
就是将前面类型的与后面类型对比,过滤出前面独有的属性
实现原理
/**
* Exclude from T those types that are assignable to U
*/
type Exclude<T, U> = T extends U ? never : T;
Example
const str: Exclude<"a" | "1" | "2", "a" | "y" | "z"> = "1";
//const str: '1'|'2' = '1';
Extract(取出)
与 Exclude 相反,针对联合类型,排除不同的的,取出相同的
实现原理
/**
* Extract from T those types that are assignable to U
*/
type Extract<T, U> = T extends U ? T : never;
Example
export type PersonAttr = "name" | "age";
export type StudentAttr = "name" | "age" | "class" | "school";
const student1: Extract<StudentAttr, PersonAttr> = "name";
// const student1: "name" | "age" = "name";
NonNullable(不能为 null)
实现原理
/**
* Exclude null and undefined from T
*/
type NonNullable<T> = T extends null | undefined ? never : T;
Example
export interface Student {
name: string;
age: number;
}
const student1: NonNullable<Student | undefined | null> = null;
// 不能将类型“null”分配给类型“Student”。
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;
Example
export interface Student {
name: string;
age: number;
}
export interface StudentFunc {
(name: string, age: number): Student;
}
const student1: Parameters<StudentFunc>;
// const student1: [name: string, age: number]
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;
Example
export interface Student {
name: string;
age: number;
}
export interface StudentConstructor {
new (name: string, age: number): Student;
}
const student1: ConstructorParameters<StudentConstructor>;
// const student1: [name: string, age: number]
ReturnType(返回类型)
获取传入函数的返回类型
实现原理
/**
* Obtain the return type of a function type
*/
type ReturnType<T extends (...args: any) => any> = T extends (
...args: any
) => infer R
? R
: any;
Example
export interface Student {
name: string;
age: number;
}
export interface StudentFunc {
(name: string, age: number): Student;
}
const student1: ReturnType<StudentFunc> = {};
// const student1: Student
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;
Example
const Student = class {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
showInfo() {
console.log("name: ", this.name, "age: ", this.age);
}
};
const student1: InstanceType<typeof Student> = new Student("张三", 20);
// const student1: Student
Uppercase(大写)
实现原理
/**
* Convert string literal type to uppercase
*/
type Uppercase<S extends string> = intrinsic;
Example
export type StudentSexType = "male" | "female";
const studentSex: Uppercase<StudentSexType> = "MALE";
Lowercase(小写)
实现原理
/**
* Convert string literal type to lowercase
*/
type Lowercase<S extends string> = intrinsic;
Example
export type StudentSexType = "MALE" | "FEMALE";
const studentSex: Lowercase<StudentSexType> = "male";
Capitalize(首字母大写)
实现原理
/**
* Convert first character of string literal type to uppercase
*/
type Capitalize<S extends string> = intrinsic;
Example
export type StudentSexType = "male" | "female";
const studentSex: Capitalize<StudentSexType> = "Male";
Uncapitalize(首字母小写)
实现原理
/**
* Convert first character of string literal type to lowercase
*/
type Uncapitalize<S extends string> = intrinsic;
Example
export type StudentSexType = "MALE" | "FEMALE";
const studentSex: Uncapitalize<StudentSexType> = "mALE";
操作符
keyof 键值获取
keyof 可以用来取得一个对象接口的所有 key 值.
keyof 产生联合类型
interface Foo {
name: string;
age: number;
}
type T = keyof Foo;
// T -> "name" | "age"
in 遍历属性
in 只能用在类型的定义中,可以对枚举类型进行遍历
type Obj = {
[p in T]: any;
};
// Obj -> { a: any, b: any }
typeof 代表取某个值的 type
const a: number = 3;
// 相当于: const b: number = 4
const b: typeof a = 4;
instanceof 用于检测是否在原型链上
function logValue(x: Date | string) {
if (x instanceof Date) {
console.log(x.toUTCString());
} else {
console.log(x.toUpperCase());
}
}
几个特殊操作符
空值合并运算符 ??
空值合并运算符(??)是一个逻辑运算符。当左侧操作数为 null 或 undefined 时,其返回右侧的操作数。否则返回左侧的操作数。
let x = foo ?? bar();
// 等价于
let x = foo !== null && foo !== undefined ? foo : bar();
与逻辑或(||)操作符不同,逻辑或会在左操作数为 falsy 值时返回右侧操作数。也就是说,如果你使用 || 来为某些变量设置默认的值时,你可能会遇到意料之外的行为。比如为 falsy 值(’’、NaN 或 0)时。
可选链操作符 ?.
可选链的核心是允许我们写下如果碰到 null 或者 undefined,TypeScript 能立即停止运行的代码返回 undefined。
可选链耀眼的部分是使用 ?. 运算符来访问一个可选属性。
let x = foo?.bar.baz();
//等价于
let x = foo === null || foo === undefined ? undefined : foo.bar.baz();
注意:?. 与 && 运算符行为略有不同,因为 && 专用于 “falsy” 的值(如:空字符串、0、NaN、和 false),但是 ?. 是一个仅作用于结构上的操作符,?. 在验证有效数据如 0 或者空字符串时,它并没有使用短路验证的方式。
非空断言运算符 !
这个运算符可以用在变量名或者函数名之后,用来强调对应的元素是非 null|undefined 的
for (const key in defaults) {
options[key] = key in partialOptions ? partialOptions[key]! : defaults[key];
}
参考文章:
原文链接: https://jesse121.github.io/blog/articles/2021/09/04.html
版权声明: 转载请注明出处.