TypeScript——泛型

一、泛型语法的基本使用

1.1 认识泛型

        泛型是什么?有什么作用?当我们定义一个变量不确定类型的时候有两种解决方式:

  • 使用any:使用any定义时存在的问题:虽然 以 知道传入值的类型但是无法获取函数返回值的类型;另外也失去了ts类型保护的优势
  • 使用泛型:泛型指的是在定义函数/接口/类型时,不预先指定具体的类型,而是在使用的时候在指定类型限制的一种特性。

 1.2 泛型实现类型参数化

 1.3 泛型的基本补充

 1.4 泛型接口、类的使用

二、泛型约束、类型条件和映射类型 

 2.1 泛型约束(Generic Constraints)

 

2.2 映射类型(Mapped Types)、映射修饰符(Mapping Modifiers)

        有的时候,一个类型需要基于另外一个类型,但是你又不想拷贝一份,这个时候可以考虑使用映射类型。

        映射类型建立在索引签名的语法上,使用了 PropertyKeys 联合类型的泛型,其中 PropertyKeys 多是通过 keyof 创建,然后循环遍历键名创建一个类型。

 三、内置类型工具

3.1 条件类型(Conditional Types)

3.2 在条件类型中推断(infer)

type CalcFnType = (num1: number, num2: string) => number

// type CalcReturnType = ReturnType<CalcFnType>;
type MyReturnType<T extends (...arg: any[]) => any> = T extends (
  ...arg: any[]
) => infer R
  ? R
  : never
type CalcReturnType = MyReturnType<CalcFnType>

// type CalcParameterType = Parameters<CalcFnType>
type MyParameters<T extends (...arg: any[]) => any> = T extends (
  ...arg: infer P
) => any
  ? P
  : never
type CalcParameterType = MyParameters<CalcFnType>

 3.3 分发条件类型(Distributive Conditional Types)

 四、类型体操

4.1 Partial<Type>

        用于构造一个Type下面的所有属性都设置为可选的类型
interface Person {
  name: string
  age: number
  height: number
}

// type newPerson = Partial<Person>
type MyPartial<T> = {
  [K in keyof T]?: T[K]
}
type newPerson = MyPartial<Person>

4.2 Required<Type>

        用于构造一个Type下面的所有属性全都设置为必填的类型,这个工具类型跟 Partial 相反。

interface Person {
  name: string
  age?: number
  height?: number
}

// type newPerson = Required<Person>
type MyRequired<T> = {
  [K in keyof T]-?: T[K]
}
type newPerson = MyRequired<Person>

export {}

4.3 Readonly<Type>

        用于构造一个Type下面的所有属性全都设置为只读的类型,意味着这个类型的所有的属性全都不可以重新赋值。

interface Person {
  name: string
  age?: number
  height?: number
}

// type newPerson = Readonly<Person>
type MyReadonly<T> = {
  readonly [K in keyof T]: T[K]
}
type newPerson = MyReadonly<Person>

4.4 Record<Keys, Type>

        用于构造一个对象类型,它所有的key(键)都是Keys类型,它所有的value(值)都是Type类型。
interface Person {
  name: string
  age?: number
  height?: number
}
type CityType = "上海" | "洛杉矶"

// type newRecordType = Record<CityType, Person>
type MyRecord<K extends keyof any, T> = {
  [P in K]: T
}
type newRecordType = MyRecord<CityType, Person>
// type newRecordType = {
//   上海: Person;
//   洛杉矶: Person;
// }

4.5 Pick<Type, Keys>

        用于构造一个类型,它是从Type类型里面挑了一些属性Keys。

interface Person {
  name: string
  age?: number
  height?: number
}

// type newPickType = Pick<Person, "name">
type MyPick<T, K extends keyof T> = {
  [P in K]: T[P]
}
type newPickType = MyPick<Person, "name" | "age">

4.6 Omit<Type, Keys>

        用于构造一个类型,它是从Type类型里面过滤了一些属性Keys。

interface Person {
  name: string
  age?: number
  height?: number
}

// type newOmitType = Omit<Person, "name">
type MyOmit<T, K extends keyof T> = {
  [P in keyof T as P extends K ? never : P]: T[P]
}
type newOmitType = MyOmit<Person, "name" | "age">

4.7 Exclude<UnionType, ExcludedMembers>

        用于构造一个类型,它是从UnionType联合类型里面排除了所有可以赋给ExcludedMembers的类型。

type PropertyTypes = "name" | "age" | "height"

// type newType = Exclude<PropertyTypes, "name">
type MyExclude<T, U> = T extends U ? never : T
type newType = MyExclude<PropertyTypes, "name">

4.8 Extract<Type, Union>

        用于构造一个类型,它是从Type类型里面提取了所有可以赋给Union的类型。

type PropertyTypes = "name" | "age" | "height"

// type newType = Extract<PropertyTypes, "name">
type MyExtract<T, U> = T extends U ? T : never
type newType = MyExtract<PropertyTypes, "name">

4.9 NonNullable<Type>

        用于构造一个类型,这个类型从Type中排除了所有的null、undefined的类型。

type PropertyTypes = "name" | "age" | "height" | null | undefined

// type newType = NonNullable<PropertyTypes>

type MyNonNullable<T> = T extends null | undefined ? never : T
type newType = MyNonNullable<PropertyTypes>

4.10 ReturnType<Type>

        用于构造一个含有Type函数的返回值的类型。

type CalcFnType = (num1: number, num2: string) => number

// type CalcReturnType = ReturnType<CalcFnType>;
type MyReturnType<T extends (...arg: any[]) => any> = T extends (
  ...arg: any[]
) => infer R
  ? R
  : never
type CalcReturnType = MyReturnType<CalcFnType>

4.11 InstanceType<Type>

        用于构造一个由所有Type的构造函数的实例类型组成的类型。

// https://stackoverflow.com/questions/70364964/difference-in-typescript-between-types-instancetypetypeof-myclass-and-myc
/**
 * 在TypeScript中, 当你创建出来一个类型的事实上你做了两件事情, 比如Person
 *  1.创建一个类class Person
 *  2.创建了两个类型
 * 哪两个类型呢?
 *  1.Person
 *  2.typeof Person: 构造函数
 */
type HYInstanceType<T extends new (...args: any[]) => any> = T extends new (
  ...args: any[]
) => infer R
  ? R
  : never

class Person {
  name: string
  age: number
  constructor(name: string, age: number) {
    this.name = name
    this.age = age
  }
}

type T = typeof Person
type PersonType = InstanceType<typeof Person>

// 对于普通的定义来说似乎是没有区别的
const info: Person = { name: "why", age: 18 }
const into2: PersonType = { name: "kobe", age: 30 }

// 但是如果我们想要做一个工厂函数, 用于帮助我们创建某种类型的对象
// 这里的返回值不可以写T, 因为T的类型会是typeof Person
// 这里就可以使用InstanceType<T>, 它可以帮助我们返回构造函数的返回值类型(构造函数创建出来的对象类型)
function factory<T extends new (...args: any[]) => any>(
  ctor: T
): HYInstanceType<T> {
  return new ctor()
}

const p1 = factory(Person)

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值