TS-下篇: TS泛型编程(重点)

52 阅读2分钟

开篇

愿中国青年都摆脱冷气,只是向上走,不必听自暴自弃者流的话。能做事的做事,能发声的发声。有一分热,发一分光,就令萤火一般,也可以在黑暗里发一点光,不必等候炬火。此后如竟没有炬火:我便是唯一的光。倘若有了炬火,出了太阳,我们自然心悦诚服的消失,不但毫无不平,而且还要随喜赞美这炬火或太阳;因为他照了人类,连我都在内。——鲁迅

泛型概述

TypeScript 中的泛型编程(Generic Programming)可以让我们在编写代码时,以一种类型无关的方式处理数据。通过泛型编程,我们可以编写出通用的、可重用的代码,从而提高代码的灵活性和可维护性。泛型编程的核心就是类型参数化

泛型编程两大特性

类型参数化

类型参数化

通过声明函数或类时使用泛型。 它们定义的时候类型是模糊的, 直到调用时类型才被确定下来。一般调用的时候省略泛型,使用类型推导

function getPara<Type>(para: Type): Type {
  return para
}
const para1 = getPara<number>(123)
const para2 = getPara<string>("hello world~")

多泛型参数

function foo<T, E>(name: T, age: E): [T, E] {
  return [name, age]
}
const [name, age] = foo("kobe", 33)

泛型接口

注意: 泛型接口不能进行类型推导, 所以使用时需要传入具体类型, 泛型还有默认参数, 但既然使用了泛型就没必要使用泛型默认参数

interface IPerson<T> {
  name: T
  age: number
  id: T
}
const personObj: IPerson<string> = {
  name: "kobe",
  age: 33,
  id: "dddd"
}

泛型类

class Person<T> {
  constructor(public name: T, public id: T) {
    this.name = name
    this.id = id
  }
}
const obj = new Person("messi", "abcd")

泛型约束

在某些情况下,我们希望对泛型类型参数做一些限制,以避免一些错误发生。通过泛型约束,我们可以为泛型类型参数添加约束条件,在使用时必须满足这些条件。

interface IgetLength<T = number> {
  length: T
}
function getLengthFn<T extends IgetLength>(para: T) {
  return para
}
const res1 = getLengthFn("122334")
const res2 = getLengthFn([1, 2, 3])

泛型对象key约束

约束条件: 要求传入的key必须是传入对象中有的key

keyof 是一种索引类型查询操作符,用于获取一个对象的所有可访问属性的名称组成的联合类型

interface Iobj {
  name: string
  age: number
}
const obj: Iobj = {
  name: "messi",
  age: 33
}
function objFn<O, K extends keyof O>(obj: O, key: K) {
  return obj[key]
}
const value1 =  objFn(obj, "name")

映射类型

映射类型可以帮助我们快速创建新的类型,并在同时保留类型信息。

type MapPersonType<T> = {
  [key in keyof T]: T[key]
}
interface IPerson {
  name: string
  age: number
  id: number
}
type newPerson = MapPersonType<IPerson>