关键字,技巧了解
keyof,用来取得一个对象接口的所有 key 值
interface Point {
x: number;
y: number;
}
// type keys = "x" | "y"
type keys = keyof Point;
in 则可以遍历枚举类型
type Keys = "a" | "b"
type Obj = {
[p in Keys]: any
} // -> { a: any, b: any }
typeof 用来获取基本数据的类型
let p = {
name: 'zs',
age:10
}
function p1(parmas: typeof p) { //它会去解析p。 然后变成 parmas : { name:string, age:number}
console.log(p.age)
console.log(p.name)
}
p1(p)
注意
只能用来查询变量或者属性的类型。
无法查询其他形式的类型。比如说:返回调用的类型。extends 条件语句
extends能够用来继承一个class、interface,还能够用来判断条件类型
T extends U ? X : Y
// T U X Y 四个是占位符,分别表示四种类型;
// T extends U 表示 T类型能被赋值给U类型,,这里还涉及到TS类型兼容性;
// 条件类型的分发特性(再续)
infer 声明一个变量来承载extends条件语句中的某些待推断的类型
infer语法的限制如下:
- infer只能在条件类型的 extends 子句中使用
infer得到的类型只能在true语句中使用, 即X中使用
type Union<T> = T extends Array<infer U> ? U: never // 泛型参数T满足约束条件Array<infer U> 那么就返回这个类型变量U
type ParamType<T> = T extends (param: infer P) => any ? P : T; // 解析如果T能赋值给(param: infer P) => any 类型,就返回P,否则就返回T interface IDog { name: string; age: number; } type Func = (dog: IDog) => void; type Param = ParamType<Func>; // IDog type TypeString = ParamType<string>; // string
is和asserts
ts不会检测自定义方法的判断语句,如果需要,分发判断,就要在自定义方法里做好参数签名,不管是谓词签名is还是断言签名asserts都可以
// asserts断言
function yell(str: any) {
console.log(str); // str: any
assert(typeof str === 'string');
return str; // str: string,经过asserts断言
// 没有断言,这里str依旧是any
}
function assert(condition: any): asserts condition {
if (!condition) {
throw new Error('错误====');
}
}
// is 帮助我们实现自定义类型判断方法的类型收窄
function isNil<T>(v: T | undefined | null): v is undefined | null {
return v === undefined || v === null;
}
function test(v: number | undefined | null) {
if (!isNil(v)) {
console.log(Math.round(v));
// 没有is签名
// ts告警如下
// Argument of type 'number | null | undefined' is not assignable to parameter of type 'number'.
// Type 'undefined' is not assignable to type 'number'.ts(2345)
}
}
没有is签名告警
高级工具类型
Partial, 传入的属性变为可选项
//源码 type Partial<T> = { [P in keyof T]?: T[P] };
//示例 type Animal = { name: string, category: string, age: number, eat: () => number } type PartOfAnimal = Partial<Animal>; //PartOfAnimal继承animal全部属性,但是全部可选
Required, 将传入的属性变为必选项,与Partial相反
//源码 type Required<T> = { [P in keyof T]-?: T[P] };
Mutable, 将类型的属性「变成可修改」
//源码 type Mutable<T> = { -readonly [P in keyof T]: T[P]; };
Readonly, 将类型的属性「变成只读」,相反
-readonly,就是移除子属性的 readonly 标识。//源码 type Readonly<T> = { readonly [P in keyof T]: T[P] };
Record,将 K 中所有的属性的值转化为 T 类型
//源码 type Record<K extends keyof any, T> = { [P in K]: T };
// 示例1 interface PageInfo { title: string; } type Page = "home" | "about" | "contact"; const nav: Record<Page, PageInfo> = { about: { title: "about" }, contact: { title: "contact" }, home: { title: "home" }, }; // 示例2 type keys = 'A' | 'B' | 'C' const result: Record<keys, number> = { A: 1, B: 2, C: 3 }
// 示例3 Record<string, string | string[]> // 相当于 interface api { [key: string]: string | string[]; }
Pick ,选择性继承,从 T 中取出 一系列 K 的属性,
//源码 type Pick<T, K extends keyof T> = { [P in K]: T[P] };
//示例 interface User { id: number; age: number; name: string; }; // 相当于: type PartialUser = { id?: number; age?: number; name?: string; } type PartialUser = Partial<User> // 相当于: type PickUser = { id: number; age: number; } type PickUser = Pick<User, "id" | "age">
Omit ,忽略继承。和Pick都是继承,但是key的获取方式相反。
//源码 type Omit = Pick<T, Exclude<keyof T, K>> // 使用 type PickUser = Omit<User, 'name'> // 相当于: type PickUser = { id: number; age: number; }
Extract ,提取
Exclude 的作用是提取出 T 包含在 U 中的元素,其实就是从T找出T和U的交集
// 源码 type Extract<T, U> = T extends U ? T : never;
// 示例 type T = Extract<1 | 2, 1 | 3> // -> 1
Exclude ,排除,如果 T 是 U 的子类型的话,那么就会返回 X,否则返回 Y
Exclude 的作用是从 T 中找出 U 中没有的元素, 换种更加贴近语义的说法其实就是从T 中排除 U
//源码 type Exclude<T, U> = T extends U ? never : T;
interface student { name: string; addr: string; } type ExcludeKeys = Exclude<keyof User, keyof student>; // type ExcludeKeys = 'addr';
// 示例 type T = Exclude<1 | 2, 1 | 3> // -> 2
ReturnType ,获取函数返回值
// 源码 type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;
NonNullable ,从类型 T 中排除 null 和 undefined
// 源码 type NonNullable<T> = T extends null | undefined ? never : T;
//示例 type Msg = string | null | number | undefined; type MsgNonNullable = NonNullable<Msg>; // 等价 type nonNullable = string | number;
Nullable 可以为null
// 源码 declare type Nullable<T> = T | null;
//示例 type Msg = string | number; type MsgNonNullable = Nullable<Msg>; // 等价 type nonNullable = string | number | null;
Parameters ,获取函数的参数类型
// 源码 type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;
//示例 const updata = (a: string, b: number) => ({a, b}); type ArrType = Parameters<typeof updata> // ArrType => [a: string, b: number]
ConstructorParameters ,获取构造函数的参数类型
和Parameters区别就是参数类型限制为abstract抽象类
// 源码 type ConstructorParameters<T extends abstract new (...args: any) => any> = T extends abstract new (...args: infer P) => any ? P : never;
InstanceType ,获取实例类型,通过传入的抽象类参数获取到他的实例类型
// 源码 type InstanceType<T extends abstract new (...args: any) => any> = T extends abstract new (...args: any) => infer R ? R : any;
//示例 const updata = (a: string, b: number) => ({a, b}); type ArrType = Parameters<typeof updata> // ArrType => [a: string, b: number]
自定义工具类型
NonFunctionKeys ,获取对象中所有非函数类型属性的 key
// 实现 type NonFunctionKeys<T extends object> = { [K in keyof T]-?: T[K] extends Function ? never : K }[keyof T]
NonFunction ,剔除对象中的函数的新类型
// 实现 type NonFunction<T extends object> = Pick<T,NonFunctionKeys<T>>
AxiosReturnType ,获取axios方法返回的AxiosPromise<Resp>中Resp类型
// 实现 import { AxiosPromise } from 'axios' type AxiosReturnType<T> = T extends (...args: any[]) => AxiosPromise<infer R> ? R : any
ArrayElement ,提取数组成员类型
一个思路是 用 extends 限制数组类型, 然后用数组 key 类型为 number 的特性取出其属性类型
// 实现 type ArrayElement<T extends readonly unknown[]> = T[number]; type AEL = ArrayElement<[number, string]>; // number | string
第二种写法的核心思路就是用 infer 来隐射 数组的属性类型
// 实现 type ArrayElement<A> = A extends readonly (infer T)[] ? T : never
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。