TypeScript泛型详解
序言
TypeScript
已经广泛应用在前端项目中,甚至有成为前端事实标准的趋势,目前已经更新到了4.9.0
版本,它作为JavaScript
的超集为JS补充了类型校验一环,js是动态类型的语言,所以对于变量的类型常常无法准确定义,这对于小型项目来说问题不大,开发人员自己是可以把控的,但随着前端的高速发展,前端项目越来越巨大、团队成员也越来越多,动态类型就会让项目的维护越来越困难,TS就是来解决这个痛点的。
类型定义
基本类型定义
string
boolean
number
undefined
null
symbol
bigint
any
任意类型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
-
interface
interface Point { x: number; y: number; }
-
type
type 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