玩转 Ts 类型声明。Ts 体操基础
Ts 基础声明
类型声明 / 接口类型声明 / 泛型 …
// 别名
type Name = string;
const name: Name; // const name:string;
type Info = { [key: string]: number };
const info: Info = { a: 1, b: 2 };
type Person1 = [age: number, name: string, date: any];
type Person2 = { age: number; name: string; date: any };
const p1: Person1 = [18, 'zzh', {}];
const p2: Person2 = { age: 18, name: 'zzh', date: {} };
// 接口类型声明
interface Car1 {
engin: string;
run(): void;
}
type Car2 = {
engin: string;
run(): void;
};
// 继承
interface MotorCar1 extends Car1{
chongdian(){}
}
inteface MotorCar2 extends Car2{
chongdian(){}
}
// 实现
class MyCar implements MotorCar1{...}
class MyCar implements MotorCar2{...}
// 联合类型
type OperationNumber = 1 | 2 | 3 | 4;
type OperationType = 'Add' | 'Delete' | 'Update';
type DataType = string | number | boolean;
// 枚举
enum Operation {
Add = 1,
Delete,
Update,
}
// 泛型 集合,数组
Set<string>
Map<string,Array<string>>
const info:Map<string,Array<string>> = new Map();
info.set('name',[''])
info.set('name',[1,2])// ts类型错误警告
// 泛型类
Promise<number>
new Promise<number>((res)=>res(1000))
// 自定义泛型类 和 泛型方法
class Test<T>{
name:T;
}
type Data = { a:number,b:string }
class Test<T,D extends Data>{
name:T;
data:D;
}
function handData<T>():Array<T> {}
Ts 内置工具
-
keyof T 获取 T 类型的所有属性名的联合类型
type Keys = keyof Date interface Test{ name:string; age:number; data:Array<Test> } type Keys = keyof Test = 'name' | 'age' | 'data'
-
as 作为断言工具
Omi<T,K> 将K 从 T 删除掉,组成新的声明 // 自定义实现Omit type Omit2<T,K> = { [P in keyof T as P extends K ? never : P ]:T[P] // 详解 [ (P in keyof T) //循环变量T的所有Key =>P as (P extends K ? never : P) // 如果P 满足 K 就排除 ]:T[P] }
-
& 将两种合并
type Test = { title: string} & { name: string } = {title: string; name: string } // Test 查看后会包含& // 克隆一份 去掉& type Clone1<T> = Pick<T ,keyof T> = {[P in keyof T]:T[P]} type Test2= Clone1<Test>
-
typeof 获取具体实例的类型
const func = () => { return ''; }; type A1 = () => string; type A2 = typeof func;
-
extends 类型声明时标识继承,条件判断是表示 == 可 >=。 见下 extends 扩展
// 继承 interface A extends Object{} function<T extends string | number | symbol>(data:T):T[]{} // 条件判断 type A<T> = T extends string ? true : false // type C = A<string> = true
-
Partial 将属性全部转为可选值类型
interface Person { age: number; name: string; sex: string; } // 进行属性可选值 转换 type PersonOptional = Partial<Person>; // 转换后的效果 interface PersonOptional { age?: number; name?: string; sex?: string; }
-
Required 和 Partial 相反 所有属性都不是可选值
interface PersonOptional { age: number; name: string; sex?: string; } // 转换 type Person = Required<PersonOptional>; // 转换后的效果 interface Person { age: number; name: string; sex: string; }
-
Readonly 将属性全部包装为只读
-
Pick 将指定的属性抽取出来形成新的类型
interface Person { age: number; name: string; sex: string; } // 现在仅仅需要 age 和 name 属性 type BasePerson = Pick<Person,'age'| 'name'> = { age: number; name: string; }
-
Record 将指定的属性名,都指定为某个类型,并组成一个接口类型
type Test1 = Record<'a'|'b'|'c',string> = { a:string; b:string; c:string } type Test2 = Record<string,Date> = { [x:string]:Date } type Rect = Record<"x" | "y", number> = { x:number,A y:number, }
-
Exclude<A,B> 去掉 A 中的一部分(A,B 重合的部分)。
-
Extract<A,B> 将重合的部分取出,生产新的申明,取交集
type A = string | symbol | 1; type B = string | number | 1; type C = Exclude<A, B>; // === symbol type D = Extract<A, B>; // string | 1
-
Omit<K,T> 把 T 从 K 中剔除
// 支持接口属性剔除 type Person = { name: string; age: number }; type Age = Omit<Person, 'name'>;
type Age = Omit<'name' | 'age' | 'sex', 'name'>; // Age不等于 'age' | 'sex' //dome: 可以剔除联合类型的Omit type GetK<T> = { [P in keyof T]: P }[keyof T]; type Omit2<T extends keyof any, K extends keyof any> = GetK< Omit<Record<T, number>, K> >; // === type Omit2<T extends keyof any, K extends keyof any, _D = Omit<Record<T, number>, K>> = { [P in keyof _D]: P }[keyof _D]; type Age2 = Omit2<'name' | 'age' | 'sex', 'name'>; // 'age' | 'sex'
-
ReturnType 获取函数的返回值类型
-
Parameters 获取函数的参数类型
type GetValue = (name: string, callBack: () => number) => Promise<number>; type Params = Parameters<GetValue>; // [name:string,callBack:()=>number] type Return = ReturnType<GetValue>; // Promise<number> type NewFunc = (this: Window, ...args: Params) => Return;
-
ConstructorParameters 获取构造函数的参数
-
InstanceType 构造函数的实例化的值类型
interface Dome { // new(age:number):this 多构造有疑问 new (name: string, age: number): this; } type A = ConstructorParameters<Dome>; type B = InstanceType<Dome>;
扩展
-
keyof 和 [] 配合
type Test = { name: string; age: number }; type Dome1<T = Test> = { [K in keyof T]: T[K] }; function pluck3<T = Test, K = keyof T>(): T[K][] { return Object.values(t); }
// 取值 联合 type GetKey<U extends ObjectProps, Keys extends keyof U = keyof U> = { [K in Keys]: U[K]; }[Keys];
-
infer 将已有的类型,声明为全局类型,进行使用
//1: 获取数组具体泛型类型 type GetA<T extends any[]> = T extends Array<infer P> ? P : any; type AA = GetA<string[]>; // AA = string //2: 数组值进行使用 获取数组第一个值 type GetB<T extends any[]> = T extends [infer P, ...infer PS] ? P : any; type AA = GetB<[1, 2, 3, 4]>; // AA = 1 //3: 函数参数 更换函数声明 type ExtendFunc<T extends (...args: any[]) => any> = T extends ( ...args: infer P ) => infer U ? (this: Window, ...args: P) => U | string : T; type C = ExtendFunc<(a: string, b: number) => Date>; // C = (this:Window,a: string, b: number)=>Date | string
-
循环
- 递归调用
- 分布式 当类型参数 T 为联合类型时,会对没一项进行操作
- 映射 T 固定写法 [K in keyof T]
// 递归调用 见CreateArray,Awaited 系统提供 获取异步返回值 type C = Awaited<Promise<string>>; // C = string //分布式 type Dome2<T> = T extends number ? T : 'No'; type Dome22 = Dome2<1 | 2 | 3 | string>; // 1| 2|3|'NO' // 映射 type Dome3<T> = { [P in keyof T]: string }; type Dome33 = Dome3<{ name: 1; age: 2 }>; //{name:string,age:string}
-
extends 扩展
interface B { a: string; } interface A extends B { b: number; } // 某些情况无法正确判断 type C = A extends B ? true : false; // C = true // 变形 进行判断 type isEqualA<X, Y> = [X] extends [Y] ? [Y] extends [X] ? true : false : false; declare type isEqualB<X, Y> = (<T>() => T extends X ? 1 : 2) extends < T >() => T extends Y ? 1 : 2 ? true : false; type C2 = isEqualA<A, B> extends true ? true : false; // C == false // 局限 无法对 any进行判断 type C3 = isEqualA<A, any> extends true ? true : false; // C == true
-
特殊字段使用 ‘number’ ‘length’… 属性名
// 数组转元组 type Dome1<T extends any[]> = T[number]; type Dome1_1 = Dome1<[1, 2, 3, 4]>; // == 1|2|3|4 // 元组转数组 type Dome2<T extends string | number | symbol> = T[]=[T];
// 创建数组 // 递归调用 type CreateArray< Len extends number, D extends unknown = 1, R extends any[] = [] > = R['length'] extends Len ? R : CreateArray<Len, D, [...R, D]>; type C = CreateArray<5, 10>; //[10,10,10,10,10]
-
对字符串的处理
-
转字符串
// 将类型转为字符串 type All = null | undefined | number | string | boolean | bigint; type StringifY<T extends All> = `${T}`; type A1 = StringifY<1>; //'1' type null1 = StringifY<null>; //'null' // 分割字符 type ChartDeep<T, Acc> = T extends `${infer Char}${infer OChar}` ? ChartDeep<OChar, Acc | Char> : Acc; type ALLChar = ChartDeep<'abcdef', never>; // a |b |...
-
字符串比配模式
// 匹配字符串 infer 将其声明为变量 // dome1:去掉字符串前面的空格 制表符 换行 [一次只能匹配一个字符] type LeftTrim<T extends string> = T extends `${ | ' ' | '\t' | '\n'}${infer Value}` ? LeftTrim<Value> : T; // RealStr= 'ABCD' type RealStr = LeftTrim<' \t \n ABCD'>; // dome2:字符串替换 type ReplaceAll< S extends string, F1 extends string, T1 extends string > = S extends `${infer A}${F1}${infer C}` ? ReplaceAll<`${A}${T1}${C}`, F1, T1> : S; // 循环匹配 type RealReplace2 = ReplaceAll<'猪猪朱猪朱', '朱', '猪'>; //猪猪猪猪猪
-
-
数字
type NumberLike = number | `${number}`; // 只能是数字或者数字字符串 function isNumber(n: NumberLike) {} isNumber(1); isNumber('1.1'); isNumber('ans'); // 会被警告
-
数组
// 匹配模式 type DomeA<T extends unknown[]> = T extends [...infer A, infer B] ? A : never; // 固定数组的各个值类型 function domeB(...args: [boolean, Date, object]) {} domeB(false, new Date(), {}); // 只能这样传递固定类型的值 // 联合类型转数组 type A<T extends string | number | symbol> = T[]; // 数组转联合类型 type B<T extends any[] = [1, 2, 3, 'sss']> = T[number]; // 获取interface所有key type GetKeys<T> = T extends { [key: string]: any } ? keyof T : never; // - 联合类型 type GetKeysDome1 = GetKeys<{ a: number; b: string }>; // -- key 集合 ['a' | 'b'] type GetKeysDome1 = GetKeys<{ a: number; b: string }>[];
-
接口类型或者 class 处理
interface O { id: number; value: string; item: Array<string>; } type Device = { takePhoto(): Promise<any>; close(): void; test: number; };
-
获取 key ‘id’ | ‘value’ | ‘item’
// 方式1 type Keys1 = keyof O; // 方式2 type Keys2 = { [K in keyof O]: K }[keyof O];
-
获取所有值得类型的联合
// 方式1 type Value1 = O[keyof O]; // 方式2 type Value2 = { [K in keyof O]: O[K] }[keyof O];
- 联合类型处理
// 可将联合类型转 交叉 来源于(Vue EmitFun) // Func1 | Func2 ===>Func1 & Func2 type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never; type Dome= { aa(name: number): void; bb(name: string): number; }; type Func1 = ((event: 'aa', name: number) => void) | ((event: 'bb', name: string) => number) //Dome 获取 //({} as Func1)('aa',1) 不可行 type Func2 = UnionToIntersection<Func> // ((event: 'aa', name: number) => void) & ((event: 'bb', name: string) => number); ({} as Func2)('aa',1) 可行
- 联合类型处理
-
将具体的类转为接口
Date ==>DateAble type AA<T> = {[K in keyof T]: T[K]} type DataAble = AA<Date>
-
工具
// 属性 排除 type Key1<T, E extends string | number | symbol> = keyof Omit<T, E>; // 属性满足 type Key2<T, E extends string | number | symbol> = E extends keyof T ? E : never; // 值类型满足 type Value1<T, E> = { [K in keyof T]: T[K] extends E ? K : never; }[keyof T]; // 值类型排除 type Value2<T, E> = { [K in keyof T]: T[K] extends E ? never : K; }[keyof T]; // 属性名和属性值类型 条件满足。筛选出满足的属性名联合类型 // 属性名 排除 K , 值得类型 排除E type ValidKey4< T, K extends string | number | symbol, E extends any = any > = Extract<Key1<T, K>, Value2<T, E>>; // type qq = ValidKey4<AB, 'run' | 'fly', string> // age // 属性名 排除 K , 值得类型 满足E type ValidKey1< T, K extends string | number | symbol, E extends any = any > = Extract<Key1<T, K>, Value1<T, E>>; // type qq = ValidKey1<AB, 'run' | 'fly', string> //=name // 属性名 满足 K , 值得类型 排除E type ValidKey3< T, K extends string | number | symbol, E extends any = any > = Extract<Key2<T, K>, Value2<T, E>>; //type qq = ValidKey3<AB, 'run' | 'fly', string> // fly // 属性名 满足 K , 值得类型 满足E type ValidKey2< T, K extends string | number | symbol, E extends any = any > = Extract<Key2<T, K>, Value1<T, E>>; //type qq = ValidKey2<AB, 'run' | 'fly', string> // run
class AB { name: string = 'AB'; run: string = 'aaa'; count: number = 1; age(a: number): number { return 1; } fly(c: string, d: Date): Promise<number> { return Promise.resolve(1); } } // dome1: 排除属性名 U,满足值类型 E 组合成新的接口类型 type GetInterface2< T, U extends string | number | symbol, E extends any = any > = Pick<T, ValidKey1<T, U, E>>; type A2 = GetInterface2<AB, 'age'>; type A5 = GetInterface2<AB, never, string>; type A6 = GetInterface2<AB, never, number>; type A3 = GetInterface2<AB, 'age', (...args: any[]) => any>; type A4 = GetInterface2<AB, 'name', (...args: any[]) => number>; // dome2:属性名,值类型 都满足 type GetInterface3< T, U extends string | number | symbol, E extends any = any > = Pick<T, ValidKey2<T, U, E>>;
-
- 技巧
- 联合类型
联合类型转 & ==>({a:number} |{b:string} === >{a:number,b:string}) UnionToIntersection // Func1 | Func2 ===>Func1 & Func2 // obj1 | obj2 ===> obj1 & obj2 type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never; 1:联合类型会进行循环 2:infer 赋值 3:infer 会进行 & (??)
- 联合类型