🚐 TypeScript 泛型
软件工程的主要目的是构建不仅仅明确和一致的 API,还要让你的代码具有很强的可重用性:
- 比如我们可以通过函数来封装一些 API,通过传入不同的函数参数,让函数帮助我们完成不同的操作;
- 但是对于参数的类型是否也可以参数化呢?
类型的参数化:
实现需求:封装一个函数,传入一个参数,并返回这个参数。
按照 TypeScript 的思想,要考虑这个参数和返回值的类型需要一致。
function foo(arg: number): number { return arg }
1
2
3拓展到更多的类型(
string
、boolean
等类型):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
2
3
可以使用两种方式来调用它:
通过
<类型>
的方式传递给函数。通过类型推导,自动推导出我们传入变量的类型。在这里会推导出它们是字面量类型的,因为字面量类型对于上面的函数是适用的。
foo<string>('abc') foo<number>(123)
1
2foo('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
2
3
4
5
6
7
8
9
10
11
12
# 泛型约束
有时候希望传入的类型有某些共性,但是这些共性可能不是在同一种类型中:
比如
string
和array
都是有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
编辑 (opens new window)
📢 上次更新: 2022/09/02, 10:18:16