1

关键字,技巧了解

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语法的限制如下

  1. infer只能在条件类型的 extends 子句中使用
  2. 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签名告警
image.png


高级工具类型

  1. 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全部属性,但是全部可选
  2. Required, 将传入的属性变为必选项,与Partial相反

    //源码
    type Required<T> = { [P in keyof T]-?: T[P] };
  3. Mutable, 将类型的属性「变成可修改」

    //源码
    type Mutable<T> = {
      -readonly [P in keyof T]: T[P];
    };
  4. Readonly, 将类型的属性「变成只读」,相反
    -readonly,就是移除子属性的 readonly 标识。

    //源码
    type Readonly<T> = { readonly [P in keyof T]: T[P] };
  5. 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[];
    }
  6. 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">
  7. Omit ,忽略继承。和Pick都是继承,但是key的获取方式相反。

    //源码
    type Omit = Pick<T, Exclude<keyof T, K>>
    
    // 使用
    type PickUser = Omit<User, 'name'>
    // 相当于: type PickUser = { id: number; age: number; }
  8. Extract ,提取

    Exclude 的作用是提取出 T 包含在 U 中的元素,其实就是从T找出T和U的交集
    // 源码
    type Extract<T, U> = T extends U ? T : never;
    // 示例
    type T = Extract<1 | 2, 1 | 3> // -> 1
  9. 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
  10. ReturnType ,获取函数返回值

    // 源码
    type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;
  11. 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;
  12. 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]
  13. ConstructorParameters ,获取构造函数的参数类型

    和Parameters区别就是参数类型限制为abstract抽象类
    // 源码
    type ConstructorParameters<T extends abstract new (...args: any) => any> = T extends abstract new (...args: infer P) => any ? P : never;
  14. 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]

自定义工具类型

  1. NonFunctionKeys ,获取对象中所有非函数类型属性的 key

    // 实现
    type NonFunctionKeys<T extends object> = { [K in keyof T]-?: T[K] extends Function ? never : K }[keyof T]
  2. NonFunction ,剔除对象中的函数的新类型

    // 实现
    type NonFunction<T extends object> = Pick<T,NonFunctionKeys<T>>
  3. AxiosReturnType ,获取axios方法返回的AxiosPromise<Resp>中Resp类型

    // 实现
    import { AxiosPromise } from 'axios'
    type AxiosReturnType<T> = T extends (...args: any[]) => AxiosPromise<infer R> ? R : any
  4. 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

肥皂泡
382 声望6 粉丝

码农