玩转 Ts 类型声明。Ts 体操基础

玩转 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>KT 删除掉,组成新的声明
      // 自定义实现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:联合类型会进行循环
      2infer 赋值
      3infer 会进行 &  (??)
      
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值