# 泛型

泛型是指一种在定义接口、类或函数的时候,不预先指定具体的类型,等到使用的时候再指定具体类型的特性

# 举个🌰

  function initArr(val: any, count: number): any[] {
    const arr: any[] = []
    for (let i = 0; i < count; i++) {
      arr.push(val)
    }
    return arr
  }
  const arr1 = initArr(123.111, 3)
  const arr2 = initArr('Ethan', 3)
  console.log(arr1[0].toFixed(2), arr2[0].split(''))
  // 元素类型为any的话,操作元素的时候没有智能提示(对应元素类型的方法名或错误提示)

# 泛型函数

  function initArr2<T>(val: T, count: number): T[] {
    // const arr: T[] = []
    const arr: Array<T> = []
    for (let i = 0; i < count; i++) {
      arr.push(val)
    }
    return arr
  }
  const arr3 = initArr2<number>(111, 3)
  console.log(arr3[0].toFixed(2)) // 有提示信息
  // console.log(arr3[0].split(2)) // 报错:类型“number”上不存在属性“split”

多个泛型参数

 function foo<K, V>(key: K, val: V): [K, V] {
    return [key, val]
  }
  console.log(foo(1, '2')) // [1, '2']

# 泛型接口

定义接口时,接口中的属性/方法定义为泛型类型

使用接口时,再指定具体的数据类型

interface IbaseCRUD<T> {
    data: T[]
    add: (t: T) => void
    getById: (id: number) => T
  }
  class User {
    id?: number // id主键自增
    name: string // 姓名
    age: number // 年龄

    constructor(name, age) {
      this.name = name
      this.age = age
    }
  }
  class UserCRUD implements IbaseCRUD<User> {
    data: User[] = []

    add(user: User): void {
      user = { ...user, id: Date.now() }
      this.data.push(user)
      console.log('add_user', user)
    }

    getById(id: number): User {
      return this.data.find(item => item.id === id)
    }
  }

  const userRUD = new UserCRUD()
  userRUD.add(new User('Ethan', 30))
  userRUD.add({ name: 'Linna', age: 30 }) // 符合class User
  // userRUD.add({ name: 'Ryan', age: 6, sex: 'Male' }) // 对象文字可以只指定已知属性,并且“sex”不在类型“User”中
  console.log(userRUD.data)

# 泛型类

定义类时,类中的属性/方法定义为泛型类型

创建类实例时,再指定具体的数据类型

  class GNumber<T> {
    zero: T
    add: (x: T, y: T) => T
  }

  let gnum = new GNumber<number>()
  gnum.zero = 0
  gnum.add = function (x, y) {
    return x + y
  }

  let gstr = new GNumber<string>()
  gstr.zero = 'abc'
  gstr.add = function (x, y) {
    return x + y
  }

  console.log(gnum.add(gnum.zero, 66)) // 66
  console.log(gstr.add(gstr.zero, 'def')) // abcdef

# 泛型约束

当没有泛型约束时,会导致不清楚泛型拥有哪些属性可操作

  function fnc<T>(x: T): void {
    // console.log(x.length) // 报错:类型“T”上不存在属性“length”。
  }

实现泛型约束

  interface Length {
    length: number
  }

  // 指定泛型约束
  function fnc2<T extends Length>(x: T): void {
    console.log(x.length)
  }

  // 必须传入符合约束类型的值
  fnc2('abc')
  // fnc2(12375) // 报错:类型“number”的参数不能赋给类型“Length”的参数