likes
comments
collection
share

TypeScript泛型详解

作者站长头像
站长
· 阅读数 37

序言

TypeScript已经广泛应用在前端项目中,甚至有成为前端事实标准的趋势,目前已经更新到了4.9.0版本,它作为JavaScript的超集为JS补充了类型校验一环,js是动态类型的语言,所以对于变量的类型常常无法准确定义,这对于小型项目来说问题不大,开发人员自己是可以把控的,但随着前端的高速发展,前端项目越来越巨大、团队成员也越来越多,动态类型就会让项目的维护越来越困难,TS就是来解决这个痛点的。

类型定义

基本类型定义

  • string
  • boolean
  • number
  • undefined
  • null
  • symbol
  • bigint
  • any 任意类型
  • never 不会被检查到的值
  • unknown 未知类型

anyunknown都表示类似未知类型,但更推荐unkown,因为使用any会被TS屏蔽类型检查,而unknown会有类型校验.

let example1: string = '1'
let example2: boolean = true
let example3: number = 1

TS提供了类型推导的能力,所以对于这些基本类型,如果在最初的时候定义了值,也可以不用显式的声明类型,TS同样可以确定变量的类型,但还是更推荐显式的声明更为清晰。

TypeScript泛型详解 TypeScript泛型详解

复杂类型定义

  • 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}
    

    interfacetype这两种方式可以通用,写法也很类似,但更推荐使用interface这种方式来定义复杂类型,因为它提供了继承的能力,可以更加容易对类型拓展和复用。

泛型

通过上面介绍的两种类型定义方式已经可以覆盖对于TS的基本使用场景,但如果我们无法确定类型的时候,要如何使用TS呢?或许你可以选择any类型,但上文中我们已经介绍过,如果你使用any类型的时候,TS会屏蔽掉类型检查,那么也就失去了我们使用TS的初衷。

TS引入了泛型来为我们解决这个问题,也就是提供一个Type类型变量,这个类型变量也可以定义为任意值,让用户来定义这个类型变量,再通过定义后的类型变量,来进行类型检查。

function printObject<Type>(obj: Type): Type {
  return obj
}

TypeScript泛型详解

TypeScript泛型详解

TypeScript泛型详解

通过泛型完成了根据不同输入类型定义了对应了类型,这样TS也可以顺利完成类型检查。

我们不仅可以在function中使用,同样可以在interfacetypeclass中使用。

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名改为数字,则会被检查错误。

TypeScript泛型详解

但在上文中我们介绍过泛型可以为任意值,也会出现一些问题。

如下,我们仍使用上文中的printObject函数

function printObject<Type>(obj: Type): Type {
  obj.length
  return obj
}

TypeScript泛型详解

当我们去访问这个变量的length时,类型变量为任意值,但并非所有类型都有这个属性,所以类型检查报错了。

为了解决这个问题:

  1. 指定变量的类型,该类型存在我们所需的属性
function printObject<Type>(obj: Type[]): Type[] {
  obj.length
  return obj
}
  1. 变量继承其他类型,拓展我们的变量类型
interface Object3 {
  length: number;
}

function printObject3<Type extends Object3>(obj: Type): Type {
  obj.length
  return obj
}

尾言

泛型的基本使用方式已经基本介绍完毕,通过泛型我们可以完成更为复杂的类型声明,TS还提供很多泛型的操作符keyoftypeofExcludeOmitRecord等,以及更多的类型,如Enums等,帮助我们更加完备的定义类型,减少any的使用,才能让TypeScript体现更大的价值。

参考资料:TypeScript官方文档

转载自:https://juejin.cn/post/7171791024023404575
评论
请登录