TypeScript泛型详解
序言
TypeScript已经广泛应用在前端项目中,甚至有成为前端事实标准的趋势,目前已经更新到了4.9.0版本,它作为JavaScript的超集为JS补充了类型校验一环,js是动态类型的语言,所以对于变量的类型常常无法准确定义,这对于小型项目来说问题不大,开发人员自己是可以把控的,但随着前端的高速发展,前端项目越来越巨大、团队成员也越来越多,动态类型就会让项目的维护越来越困难,TS就是来解决这个痛点的。
类型定义
基本类型定义
stringbooleannumberundefinednullsymbolbigintany任意类型never不会被检查到的值unknown未知类型
any和unknown都表示类似未知类型,但更推荐unkown,因为使用any会被TS屏蔽类型检查,而unknown会有类型校验.
let example1: string = '1'
let example2: boolean = true
let example3: number = 1
TS提供了类型推导的能力,所以对于这些基本类型,如果在最初的时候定义了值,也可以不用显式的声明类型,TS同样可以确定变量的类型,但还是更推荐显式的声明更为清晰。

复杂类型定义
object对象类型array数组类型function函数类型
let example4: {x: number, y: nubmer} = {x: 1, y: 2}
let example5: number[] = [1, 2, 3]
let example6: (num:number) => number = (num) => num
对于这种复杂类型,TS提供更优雅的定义方式
-
Union Types
可以将多个类型组合起来,来面对更复杂的场景
let example7: number | string = 1 -
interfaceinterface Point { x: number; y: number; } -
typetype Point = { x: number; y: number; }let example4: Point = {x: 1, y: 2}interface和type这两种方式可以通用,写法也很类似,但更推荐使用interface这种方式来定义复杂类型,因为它提供了继承的能力,可以更加容易对类型拓展和复用。
泛型
通过上面介绍的两种类型定义方式已经可以覆盖对于TS的基本使用场景,但如果我们无法确定类型的时候,要如何使用TS呢?或许你可以选择any类型,但上文中我们已经介绍过,如果你使用any类型的时候,TS会屏蔽掉类型检查,那么也就失去了我们使用TS的初衷。
TS引入了泛型来为我们解决这个问题,也就是提供一个Type类型变量,这个类型变量也可以定义为任意值,让用户来定义这个类型变量,再通过定义后的类型变量,来进行类型检查。
function printObject<Type>(obj: Type): Type {
return obj
}



通过泛型完成了根据不同输入类型定义了对应了类型,这样TS也可以顺利完成类型检查。
我们不仅可以在function中使用,同样可以在interface、type、class中使用。
interface PrintObjectFn {
<Type>(obj: Type): Type
}
let print4: PrintObjectFn = printObject
class Zoom<dogType, pigType> {
dog: dogType;
pig: pigType;
add: (animal: dogType | pigType) => dogType | pigType
}
let myZoom = new Zoom<string, string>()
myZoom.dog = 'dd'
myZoom.pig = 'pq'
myZoom.add = function(animal) {
return animal
}
如果我们把pig名改为数字,则会被检查错误。

但在上文中我们介绍过泛型可以为任意值,也会出现一些问题。
如下,我们仍使用上文中的printObject函数
function printObject<Type>(obj: Type): Type {
obj.length
return obj
}

当我们去访问这个变量的length时,类型变量为任意值,但并非所有类型都有这个属性,所以类型检查报错了。
为了解决这个问题:
- 指定变量的类型,该类型存在我们所需的属性
function printObject<Type>(obj: Type[]): Type[] {
obj.length
return obj
}
- 变量继承其他类型,拓展我们的变量类型
interface Object3 {
length: number;
}
function printObject3<Type extends Object3>(obj: Type): Type {
obj.length
return obj
}
尾言
泛型的基本使用方式已经基本介绍完毕,通过泛型我们可以完成更为复杂的类型声明,TS还提供很多泛型的操作符keyof、typeof、Exclude、Omit、Record等,以及更多的类型,如Enums等,帮助我们更加完备的定义类型,减少any的使用,才能让TypeScript体现更大的价值。
转载自:https://juejin.cn/post/7171791024023404575