背景
这两天接到了一个PC开发的任务,项目使用 React 和 TypeScript 开发的,有很多 TypeScript 类型约束的写法,之前没有过多接触,这里记录一下相关学习内容。
TypeScript Playground
官网地址:www.typescriptlang.org/play/
在这里可以进行在线学习。
Pick(采集)
Pick 可以采集已定义对象中需要的一部分生成新的类型定义
// Pick 源码
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
interface IUser {
name: string;
age: number;
sex: 0 | 1;
address: string;
weight: number;
}
type Person = Pick<IUser, 'name' | 'age'>;
/*
pick后类型:
type Person = {
name: string;
age: number;
}
*/
let person1: Person = { name: 'name', age: 1 } // 赋值正确
let person2: Person = { name: 'name', age: 1, sex: 0 } // 报错,Object literal may only specify known properties, and 'sex' does not exist in type 'Person'.
Partial(可选项)
Partial 可以把定义好的对象类型(必选+可选项)全部转化为 可选项
// Partial 源码
type Partial<T> = {
[P in keyof T]?: T[P];
};
interface IUser {
name: string;
age: number;
sex: 0 | 1;
address: string;
weight: number;
}
type Person = Partial<IUser>;
/*
Partial后类型:
type Person = {
name?: string | undefined;
age?: number | undefined;
sex?: 0 | 1 | undefined;
address?: string | undefined;
weight?: number | undefined;
}
*/
let person1: Person = { name: 'name', age: 1 } // 赋值正确
console.log(person1.name, '==', person1?.name)
Required (必选)
Required 和 Partial 的作用刚好相反,可把定义好的对象类型(必选+可选项)全部转化为 必选项
// Required 源码
type Required<T> = {
[P in keyof T]-?: T[P];
};
interface IUser {
name: string;
age: number;
sex: 0 | 1;
address: string;
weight: number;
}
type Person = Required<IUser>;
/*
Required后类型:
type Person = {
name: string;
age: number;
sex: 0 | 1;
address: string;
weight: number;
}
*/
let person1: Person = {
name: 'name',
age: 1,
sex: 0,
address: "",
weight: 0
} // 赋值正确
let person2: Person = { name: 'name'} // 报错, Type '{ name: string; }' is missing the following properties from type 'Required<IUser>': age, sex, address, weight
Readonly (只读)
Readonly 为对象类型中每一项添加前缀 Readonly
// Readonly 源码
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
interface IUser {
name: string;
age: number;
sex: 0 | 1;
address: string;
weight: number;
}
type Person = Readonly<IUser>
/*
// Readonly后类型:
type Person = {
readonly name: string;
readonly age: number;
readonly sex: 0 | 1;
readonly address: string;
readonly weight: number;
}
*/
let person1: Person = {
name: 'name',
age: 0,
sex: 0,
address: "",
weight: 0
} // 赋值正确
person1.name = 'name2' // 报错,Cannot assign to 'name' because it is a read-only property
Extract (提取/包括)
Exclude 用于处理联合类型,可以提取联合类型中的类型定义(只保留提取的联合类型)
// Extract实现源码 原理很简单
type Extract<T, U> = T extends U ? T : never;
// 联合类型
type TStringValue = '1' | '2' | '3'
type TNewStringValue = Extract<TStringValue, '1' | '2'>
// 提取后类型为:type TNewStringValue = "1" | "2"
const obj1: TNewStringValue = '1'; // 赋值'1'正确
const obj2: TNewStringValue = '2'; // 赋值'2'正确
const obj3: TNewStringValue = '3'; // 报错,Type '"3"' is not assignable to type '"1" | "2"'.
interface IUser {
name: string;
age: number;
sex: 0 | 1;
address: string;
weight: number;
}
// 对象联合类型
type Person = Extract<keyof IUser, 'name' | 'age'> // type Person = "name" | "age"
let person1: Person = 'name' // 赋值正确
let person2: Person = 'age' // 赋值正确
let person3: Person = 'sex' // 报错,Type '"sex"' is not assignable to type 'Person'.
Exclude (排除/不包括)
Exclude 用于处理联合类型,可以排除联合类型中的类型定义,作用和Extract 相反
// Exclude源码
type Exclude<T, U> = T extends U ? never : T;
type TStringValue = '1' | '2' | '3'
type TNewStringValue = Exclude<TStringValue, '1' | '2'>
// 提取后类型:type TNewStringValue = "3"
const obj1: TNewStringValue = '1'; // 报错,Type '"1"' is not assignable to type '"3"'.
const obj2: TNewStringValue= '2'; // 报错,Type '"2"' is not assignable to type '"3"'.
const obj3: TNewStringValue = '3'; // 赋值正确
interface IUser {
name: string;
age: number;
sex: 0 | 1;
address: string;
weight: number;
}
// 对象联合类型
type Person = Exclude<keyof IUser, 'name' | 'age'> // type Person = "sex" | "address" | "weight"
let person1: Person = 'sex' // 赋值正确
let person2: Person = 'address' // 赋值正确
let person3: Person = 'weight' // 赋值正确
let person4: Person = 'name' // 报错,Type '"name"' is not assignable to type 'Person'.
Omit(省略/剔除)
Omit 可以剔除已定义对象中不需要的部分生成新的类型定义
// Omit 的源码
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
interface IUser {
name: string;
age: number;
sex: 0 | 1;
address: string;
weight: number;
}
// 剔除省略不需要的属性定义
type Person = Omit<IUser, "address" | "weight">;
let person: Person = {
name: "",
age: 0,
sex: 0,
// address: '111' // 报错,Object literal may only specify known properties, and 'address' does not exist in type 'Person'
}
ReturnType (类型推导返回)
ReturnType 可以推导函数类型并返回
// ReturnType 源码
type ReturnType<T extends (...args: any[]) => any> = T extends (
...args: any[]
) => infer R
? R
: any;
function testUser() {
return {
name: 'name',
age: 1,
sex: 1
}
}
type TypeUser = ReturnType<typeof testUser>;
/*
ReturnType推导函数的类型:
type TypeUser = {
name: string;
age: number;
sex: number;
}
*/
let person: TypeUser = {
name: "",
age: 0,
sex: 0
}
NonNullable (类型中排除 null 和 undefined)
NonNullable 用于联合类型,可以排除类型定义中为 null 和 undefined 的属性
// NonNullable 源码
type NonNullable<T> = T & {};
type MaybeString = string | null | undefined;
let string1: MaybeString = null
let string2: NonNullable<MaybeString> = 'string1' // 正常赋值
let string3: NonNullable<MaybeString> = null // 报错,Type 'null' is not assignable to type 'string'.(2322)
let string4: NonNullable<MaybeString> = undefined // 报错,Type 'undefined' is not assignable to type 'string'.(2322)
使用场景
例如将定义类型 ExportIProps 转为 IProps
type ExportIProps = {
title: string,
column: Object[],
placeholder: string,
displayKey: Array<string>,
sourceList: Object[], // 数据源
showModal: boolean,
onCancel?: () => void;
}
type IProps = {
title?: string,
placeholder?: string,
sourceList: Object[], // 数据源
showModal: boolean,
onCancel?: () => void;
}
type ExportIProps = {
title: string,
column: Object[],
placeholder: string,
displayKey: Array<string>,
sourceList: Object[], // 数据源
showModal: boolean,
search: (val: string) => void;
sureAdd: (checkedList: Array<any>) => void;
onCancel?: () => void;
}
const mapStateToProps = () => ({
state: {
name: 'nameState'
},
});
type IProps = ReturnType<typeof mapStateToProps>
& Omit<ExportIProps, 'title' | 'column' | 'placeholder' | 'displayKey' | 'search' | 'sureAdd'>
& Partial<Pick<ExportIProps, 'title' | 'placeholder'>>
let p: IProps
参考
友情提示
本文同步自微信公众号 "程序员小溪" ,这里只是同步,想看及时消息请移步我的公众号,不定时更新我的学习经验。