目录

🚐 TypeScript 泛型

软件工程的主要目的是构建不仅仅明确和一致的 API,还要让你的代码具有很强的可重用性:

  • 比如我们可以通过函数来封装一些 API,通过传入不同的函数参数,让函数帮助我们完成不同的操作;
  • 但是对于参数的类型是否也可以参数化呢?

类型的参数化:

  • 实现需求:封装一个函数,传入一个参数,并返回这个参数。

  • 按照 TypeScript 的思想,要考虑这个参数和返回值的类型需要一致。

    function foo(arg: number): number {
      return arg
    }
    
    1
    2
    3
  • 拓展到更多的类型( stringboolean 等类型):

    function foo(arg: any): any {
      return arg
    }
    
    1
    2
    3

# 使用泛型实现类型参数化

虽然使用 any 是可以的,但是定义为 any 类型的时候,我们其实已经丢失了类型信息

  • 比如我们传入的是一个 number,那么希望返回的可不是 any 类型,而是 number 类型;
  • 所以,需要在函数中可以捕获到参数的类型是 number ,并且同时使用它来作为返回值的类型。

可以使用一种特性的变量「类型变量(type variable)」,它作用于类型,而不是值。

function foo<Type>(arg: Type): Type {
  return arg
}
1
2
3

可以使用两种方式来调用它:

  • 通过 <类型> 的方式传递给函数。

  • 通过类型推导,自动推导出我们传入变量的类型。在这里会推导出它们是字面量类型的,因为字面量类型对于上面的函数是适用的。

    foo<string>('abc')
    foo<number>(123)
    
    1
    2
    foo('abc')
    foo(123)
    
    1
    2
  • 在泛型中可以传入多个类型:

    function foo<T, E>(a1: T, a2: E)
    
    1
  • 在开发中看到一些常用的名称:

    • T:Type 的缩写,类型
    • K、V:key 和 value 的缩写,键值对
    • E:Element 的缩写,元素
    • O:Object 的缩写,对象

# 泛型接口

  • 在定义接口时可以使用泛型:

    interface IFoo<T> {
      initialValue: T,
      valueList: T[],
      handleValue: (value: T) => void
    }
    
    const foo: IFoo<number> = {
      initalValue: 0,
      valueList: [0, 1, 3],
      handleValue: function(value: number) {
        console.log(value)
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13

    可以设置默认值为 number 类型:

    interface IFoo<T = number> {
      initialValue: T,
      valueList: T[],
      handleValue: (value: T) => void
    }
    
    1
    2
    3
    4
    5

# 泛型类

class Point<T> {
  X: T
  y: T
  
  constructor(x: T, y: T) {
    this.x = x
    this.y = y
  }
}
const p1 = new Point(10, 20)
const p2 = new Point<number>(10, 20)
const p3: Point<number> = new Point(10, 20)
1
2
3
4
5
6
7
8
9
10
11
12

# 泛型约束

有时候希望传入的类型有某些共性,但是这些共性可能不是在同一种类型中:

  • 比如 stringarray 都是有 length 的,或者某些对象也是会有 length 属性的;

  • 那么只要是拥有 length 的属性都可以作为参数类型:

    interface ILength {
      length: number
    }
    
    function getLength<T extends ILength>(args: T) {
      return args.length
    }
    
    console.log(getLength('abc'))
    console.log(getLength(['abc', 'cba']))
    console.log(getLength({length: 100, name: 'simon'}))
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
📢 上次更新: 2022/09/02, 10:18:16