huruji / blog

红日初升,其道大光:sun_with_face::house_with_garden:请star或watch,不要fork
https://juejin.im/user/5894886f2f301e00693a3e49/posts
158 stars 11 forks source link

TypeScript 的实用类型笔记 #77

Open huruji opened 5 years ago

huruji commented 5 years ago

Partial

将泛型 T 的所有属性变为可选:

实现为:

type Partial<T> = {
    [P in keyof T]?: T[P];
};

例子:

interface IGoods {
  sku: string
  name: string
  price: number
}

let book:Partial<IGoods> = {
  sku: 'abcd',
  name: 'huruji'
}

book.price = await getPrice(book.sku)

我们可以拓展一下,支持深层次的 partial

type DeepPartial<T> = {
  [P in keyof T]?: T[P] extends Array<infer U>
    ? Array<DeepPartial<U>>
    : T[P] extends ReadonlyArray<infer U>
      ? ReadonlyArray<DeepPartial<U>>
      : DeepPartial<T[P]>
}
interface IUser {
  user: {
    name: string,
    id: number
  }
}

let huruji:DeepPartial<IUser> = {
  user: {
    name: 'huruji'
  }
}

Readonly

将泛型 T 的所有属性变为只可读(readonly):

实现为:

type Readonly<T> = {
    readonly [P in keyof T]: T[P];
};

例子:

function freeze<T>(obj:T):Readonly<T> {
  return obj
}

const user = freeze({
  name: 'huruji',
  age: 12
})

Record<K, T>

规定 key 的type

实现为:

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

例子:

type GoodProps = 'sku' | 'id' | 'name'

let iphone:Record<GoodProps, string> = {
  sku: 'f',
  id: 'a',
  name: 'd'
}

等同于定义的 interface:

interface IGoods {
  sku: string
  id: string
  name: string
}

Pick<T,K>

选取 T 的部分属性组成新的 type

实现为:

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

例子:

interface IGoods {
  sku: string
  id: string
  name: string
}

let airpod:Pick<IGoods, 'sku' | 'name'> = {
  sku: 'sdf',
  name: 'air'
}

Omit<T, K>

从类型 T 中忽略 K 属性,组成新的类型

实现为:

type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;

例子: pick 的例子等价于

interface IGoods {
  sku: string
  id: string
  name: string
}

let airpod:Omit<IGoods, 'id'> = {
  sku: 'sdf',
  name: 'air'
}

Exclude<T,U>

排除部分 T 的属性(Constructs a type by excluding from T all properties that are assignable to U.)

实现:

type Exclude<T, U> = T extends U ? never : T;

例子:

type GoodProps = 'sku' | 'id' | 'name'

type SubGoods = Exclude<GoodProps, 'name'>

let desk:Record<SubGoods, string> = {
  sku: '123',
  id: '456'
}

Extract<T, U>

T 和 U 取交集组成新的类型

实现:

type Extract<T, U> = T extends U ? T : never;

例子

type GoodProps = 'sku' | 'id' | 'name'

type People = 'age' | 'name'

let ex:Extract<GoodProps, People> = 'name'

NonNullable

从 T 中排除 null 和 undefind 类型

实现:

type NonNullable<T> = T extends null | undefined ? never : T;

例子:

type Age = number | undefined | null

let userAge:NonNullable<Age> = 12

ReturnType

获得函数类型 T 的返回类型

实现:

type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;

例子:

type T0 = ReturnType<() => string>
let name:T0 = 'huruji'

Required

将 T 中所有可选属性转换为必须属性,是 Partial 的反操作