TS的工具类型和关键字

281 阅读5分钟

内置工具类型

方法参数类型返回类型描述源码
Partial<T>T: 对象类型对象类型将T中所有属性添加可选 ?type Partial<T> = {[P in keyof T]?: T[P];}
Required<T>T: 对象类型对象类型将T中所有属性去除可选 ?type Required<T> = {[P in keyof T]-?: T[P];};
Readonly<T>T: 对象类型对象类型将T中所有属性添加readonlytype Readonly<T> = {readonly [P in keyof T]: T[P];};
Omit<T, K extends keyof any>T: 对象类型, U: 联合类型对象类型从T中排除键在K中的属性type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
Pick<T, K extends keyof T>T: 对象类型, K: 联合类型对象类型从T中挑选键在K中的属性type Pick<T, K extends keyof T> = {[P in K]: T[P];};
Exclude<T, U>T: 联合类型, U: 联合类型联合类型排除T在U中的类型type Exclude<T, U> = T extends U ? never : T;
Extract<T, U>T: 联合类型, U: 联合类型联合类型提取T在U中的类型type Extract<T, U> = T extends U ? T : never;
NonNullable<T>T: 联合类型联合类型排除T中的undefined和null类型type NonNullable<T> = T & {};
Parameters<T extends (...args: any) => any>T: 函数类型元组类型,内容根据范型决定返回函数所有参数的类型的元组type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;
ReturnType<T extends (...args: any) => any>T: 函数类型根据范型决定返回函数返回值的类型type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;

类型的方法

[P in K]: T

[P in K]: T类似于for...in,表达式返回对象类型 K是一个联合类型,P是从K迭代出来的, T为对象中值的类型

// K从联合类型'x' | 'y'中迭代,值的类型为number
type Coord = {
    [K in 'x' | 'y']: number;
};

// 得到
type Coord = {
   x: number;
   y: number;
}

// K从联合类型'x' | 'y'中迭代,值的类型为K
type Coord = { 
    [K in 'x' | 'y']: K 
};

// 得到 
type Coord = { 
    x: 'x'; 
    y: 'y'; 
}

利用映射类型进行复制

// 定义类型item
type Item = {
    a: string
    b: number
    c: boolean
}
// 定义类型ItemKeys
type ItemKeys = 'a' | 'b' | 'c';

// K从ItemKeys中迭代,值的类型为Item中对应K的类型
type Copy = { 
    [K in ItemKeys]: Item[K]
};

// 得到 
type Copy = { 
    a: string, 
    b: number, 
    c: boolean 
};

keyof

返回对象类型中的所有key的联合类型

type Item = {
    a: string
    b: number
    c: boolean
}

type ItemKeys = keyof Item; // 返回 'a'|'b'|'c'

// 优化一下Copy
type Copy = { 
    [K in keyof Item]: Item[K] 
};

// 得到 
type Copy = { 
    a: string, 
    b: number, 
    c: boolean 
};

特殊:keyof any 返回 string | number | symbol

extends

约束范型的范围

// 内置类型Record的源码
// keyof any返回联合类型 string | number | symbol
// extends 约束范性K在联合类型keyof any中

type Record<K extends keyof any, T> = {
    [P in K]: T;
};

使用

// Record 第一个范性必须属于string | number | symbol
const userInfo: Record<string, string|number> = {
    name: 'yxx',
    age: 18
}

infer

infer 推导泛型中某个属性的类型 infer 只能在 extends 的右边使用,infer P 的 P 也只能在条件类型为 True 的一边使用

// ReturnType 返回函数类型的返回值类型
// 1. 约束T为函数类型,
// 2. T extends (...args: any) => infer R 表示要推导函数的返回值类型
// 3. R就代表T的反回值类型,最后把R返回
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;

// 使用
type Func = ()=>string
let name: ReturnType<Func> = '得到Func返回值类型为string'
// Parameters返回一个元组类型,内容为函数参数类型的集合
// 约束T为函数类型,推导把函数参数的类型,即P为函数参数类型构成的元组类型,最后返回P
type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;

// 使用
type Func = (name: string, age: number)=>void
let name: ReturnType<Func> = ['sss', 100] // ReturnType<Func>表达式得到类型 [string, number]
// 把范型T约束在{data: any}中,推导data的类型,R就是T中data的类型,最后返回R
type DataType<T extends {data: any}> = T extends {data: inter R} ? R : any;

type Info = {
    data: string
}
let data: DataType<Info> = '得到Info中data的类型为string'

readonly / ? / + / -

readonly 将属性设为只读 ? 将属性设为可选

type Coord = {
    readonly [K in 'x' | 'y']: number
};

// 得到
type Coord = {
    readonly x: number;
    readonly y: number;
};

// 两个装饰符也可组合使用:

type Coord = {
    readonly [K in 'x' | 'y']?: number;
};
// 得到
type Coord = {
    readonly x?: number;
    readonly y?: number;
};

// 但这里面也有局限性,无法去除属性上已经存在的 装饰符:

type CoordOptional = {
    x?: number;
    readonly y: number;
};
type Coord = {
    [K in keyof CoordOptional]: number;
};
// 得到
type Coord = {
    x?: number;
    readonly y: number;
};

因为这个原因,社区又在 TS2.8 又对其进行了完善,可以在上面的装饰符添加 - 或 + 符号:

type CoordOptional = {
    x?: number;
    readonly y: number;
};
type Coord = {
    -readonly [K in keyof CoordOptional] -?: number;
};
// 得到
type Coord = {
    x: number;
    y: number;
};

向interfaces中添加任意属性

我们使用interfaces定义对象时,有哪些属性,是什么类型都是一一定义好了,如果我们想要向对象中添加任意属性时就可以使用 [key:string] 来定义

// tableColumnList的项
export interfaces Column {
    prop: string,
    label: string,
    //自定义key 任意值
    [key:string]: unknown,
}

const column: Column = {
    prop: 'name',
    label: '姓名',
    // 添加任意类型
    myData: 'test1'
}

as const

使用readonly、const定义对象或数组类型时只能限制变量不能直接被修改,但我们仍可以修改深层的属性 用as const来声明,可以确保所有属性都不能被修改

const list = [1,2,3]
list[0] = 100 // 可以修改

const list = [1,2,3] as const
list[0] = 100 // 不能修改

将数组转换成类型

当我们有一个数组,想定义一个该数组内容的联合类型时,使用下面这个方法

const arr = ['name', 'age', 'location', 'email'] as const;

type A = typeof arr[number];

// 得到联合类型
type A = 'name'|'age'|'location'|'email'