常见的TypeScript的工具与类型体操实现

134 阅读3分钟

内置工具与通过类型体操实现

ReturnType

  • 获取函数的返回值类型
type CalcFnType = (num1: number, num2: number) => number

function foo() {
  return 'aaa'
}

// 获取一个函数的返回值类型
type CalcReturnType = ReturnType<CalcFnType> // number
type FooReturnType = ReturnType<typeof foo> // string
  • 封装自己的 MyReturnType ,看上面的 infer

Partial

把类型全部变为可选,映射也可以实现

interface IKun {
  name: string
  age: number
  slogan?: string
}

// 类型体操 映射实现实现Partial
type MyPartial<T> = {
  [P in keyof T]?: T[P]
}

type IKunOptional = Partial<IKun>
/*
type IKunOptional = {
    name?: string | undefined;
    age?: number | undefined;
    slogan?: string | undefined;
}
*/

Require

把类型全部变为必选

interface IKun {
  name: string
  age: number
  slogan?: string
}

// 类型体操 Required
type MyRequired<T> = {
  [P in keyof T]-?: T[P]
}

type IKunRequired = Required<IKun>
type IKunRequired2 = MyRequired<IKun>
/*
type IKunOptional = {
    name: string;
    age: number;
    slogan: string;
}
*/

Readonly

把类型全部变为只读属性

interface IKun {
  name: string
  age: number
  slogan?: string
}

// 类型体操 
type MyReadonly<T> = {
  readonly [P in keyof T]: T[P]
}

type IKunOptional = Readonly<IKun>

Record<Keys,Type>

用于构造一个对象类型,它所有的 key (键)都是 Keys 类型,它所有的 value (值)都是 Type 类型

interface IKun {
  name: string
  age: number
  slogan?: string
}

// 类型体操 
// in后面接联合类型 keyof可以获取联合类型
// 所以我们需要通过 extends keyof any 确保获取到的Keys为联合类型
type MyRecord<Keys extends keyof any, T> = {
  [P in Keys]: T
}

type t1 = "上海" | "北京" | "洛杉矶"
// type IKuns = Record<t1, IKun>
type IKuns = MyRecord<t1, IKun>
/*
 type IKun2 = {
    上海: IKun;
    北京: IKun;
    洛杉矶: IKun;
  }
 */

const ikuns: IKuns = {
  '上海': {
    name: 'aaa',
    age: 10
  },
  '北京': {
    name: 'bbb',
    age: 11
  },
  '洛杉矶': {
    name: 'zzz',
    age: 3
  }
}

Pick<Type,Keys>

构造类型,它是从 Type 类型里面挑选了一些属性 Keys

interface IKun {
  name: string
  age: number
  slogan?: string
}

// 类型体操 Required
// in后面接联合类型 keyof可以获取联合类型
// 所以我们需要通过 extends keyof any 确保获取到的Keys为联合类型
type MyPick<T, K extends keyof T> = {
  [P in K]: T[P]
}

// 从IKun类型中获取slogan、name类型重新组成新的类型
// type IKuns = Pick<IKun, "slogan" | "name">
type IKuns = MyPick<IKun, "slogan" | "name">
/*
  type IKuns = {
    slogan?: string | undefined;
    name: string;
  }
 */

Omit<Type,Key>

用于构造一个类型。过滤 Type 类中里面的一些属性 Keys

interface IKun {
  name: string
  age: number
  slogan?: string
}

// 类型体操 
type MyOmit<T, K extends keyof T> = {
  // keyof T(name|age|slogan)作为P类型 是否继承Key(slogan) 继承删除 不继承保留
  [P in keyof T as P extends K ? never : P]: T[P]
}

// 从IKun类型中过滤slogan属性
// type IKuns = Omit<IKun, "slogan">
type IKuns = MyOmit<IKun, "slogan">
/*
  type IKuns = {
    name: string;
    age: number;
  }
 */

Exclude<UnionType,ExcludedMembers>

从联合类型 UnionType 里面排除所有 ExcludedMembers 的类型

type IKun = "sing" | "dance" | "rap"

// 类型体操实现
type MyExclude<T, E> = T extends E ? never : T

// type IKuns = Exclude<IKun, "rap">
type IKuns = MyExclude<IKun, "rap">
// type IKuns = "sing" | "dance"

Extract<UnionType,ExcludedMembers>

从联合类型 UnionType 里面获取 ExcludedMembers 里面的类型

type IKun = "sing" | "dance" | "rap"

// 类型体操实现
type MyExtract<T, E> = T extends E ? T : never

// type IKuns = Extract<IKun, "rap">
type IKuns = MyExtract<IKun, "rap">
// type IKuns = "rap"

NonNullable

Type 类型中排除所有的 nullundefined 类型

type IKun = "sing" | "dance" | "rap" | null | undefined

// 类型体操实现
type MyNonNullable<T> = T extends null | undefined ? never : T

// type IKuns = NonNullable<IKun>
type IKuns = MyNonNullable<IKun>
// type IKuns = "sing" | "dance" | "rap"

InstanceType

获取实例类型

对象可以通过typeof拿到类型,在通过InstanceType拿到实例类型

vue3中获取ref<>的类型,经常使用InstanceType获取

// LoginAccount是一个组件 我们可以使用typeof拿到组件的类型,再通过InstanceType拿到组件的实例
const accountRef = ref<InstanceType<typeof LoginAccount>>()

// 类型体操实现
//  new (...args: any[]) => any为一个构造器
type MyInstanceType<T extends new (...args: any[]) => any> = T extends new (...args: any[]) => infer R ? R : never

class Person{}
type Person2 = InstanceType<typeof Person>
const p1: Person2 = new Person{}