TypeScript中的泛型使用详解

导读:本篇文章讲解 TypeScript中的泛型使用详解,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

一、泛型的概述

“泛”就是广泛的意思,”型”就是数据类型。顾名思义,泛型就是适用于多种数据类型的一种类型。

它能够帮助我们构建出复用性更强的代码。

假如有如下函数:

function sum(num: number): number {
  return num
}

此时函数的参数和返回值都必须是number类型的。

但是其它类型的数据,比如stringboolean或者自定义的Teacher等类型就没有办法使用这个函数。

虽然any可以解决这个问题,但是函数参数和返回值定义为any的时候,具体的类型信息就已经丢失了。

比如传入的是一个number,那么我们希望返回的并不是any类型,而是number类型。

所以,我们需要在函数中可以捕获到参数的类型是number,并且同时使用它来作为返回值的类型。

因此需要在这里使用一种特性的变量 – 类型变量(type variable),它作用于类型,而不是值!

二、泛型的基本使用

2.1 泛型函数示例

在定义一个函数时,不决定这些参数的类型,而是让调用者以参数的形式告知函数参数应该是什么类型。

function sum<T>(num: T): T {
  return num
}

我们可以把Type看做额外的一个参数,把类型参数化。

它可以做到, 在定义这个函数时, 不决定这些参数的类型, 而是让调用者以参数的形式告知, 这里的函数参数应该是什么类型。

2.2 传入泛型的方式

函数定义时,<>的位置就是之后泛型的传入位置,比如上面函数的<T>

传入泛型时,只要把具体的泛型传递给<T>即可。

这样函数定义时的,函数参数,和函数返回值的T类型,都会变成传入的具体参数类型。

1)通过 <类型> 的方式将泛型传递给函数

sum<number>(100) 						// 声明sum函数的泛型为number类型,并传递number类型的参数
sum<{name: string}>({ name: "zs" }) 	// 声明sum函数的泛型为{name: string}类型
sum<number[]>([15, 25]) 				// 声明sum函数的泛型为number类型的数组

2)通过类型推导,自动推到出我们传入变量的类型

在这里会推导出它们是 字面量类型的,因为字面量类型对于我们的函数也是适用的

sum(100)
sum("test")

三、常用的泛型名称

开发中可能会看到一些常用的名称,不同的名称会有不同语义化意义。

  • TType的缩写,类型

  • K、Vkeyvalue的缩写,键值对

  • EElement的缩写,元素

  • OObject的缩写,对象

四、传入多个泛型

function fun<T, E>(arg1: T, arg2: E) {
  console.log(arg1, arg2)
}

fun<number, string>(100, "test")

当一个函数有多个泛型时,可以用不同的泛型名称来标识。

上面的fun函数的参数一的类型由泛型T决定,而参数二由泛型E决定。

五、泛型接口

在定义接口的时候也可以使用泛型来对接口内的成员进行类型约束。

2.1 泛型接口的基本使用

interface IInfo<T1, T2> {
  name: T1
  age: T2
}

const info: IInfo<string, number> = {
  name: "zs",
  age: 25
}

2.2 泛型接口中的基本使用

泛型接口是没有类型推导的, 但是可以有泛型默认值。

// 泛型接口定义默认类型
interface IPerson<T1 = string, T2 = number> {
  name: T1
  age: T2
}

const p: IPerson = {
  name: "chenyq",
  age: 123
}

六、泛型类的使用

class Point<T> {
  x: T
  y: T
  z: T

  constructor(x: T, y: T, z: T) {
    this.x = x
    this.y = y
    this.z = y
  }
}

// 泛型类自动推导类型
const point1 = new Point("1.33.2", "2.22.3", "4.22.1")
// 泛型类明确泛型类型
const point2 = new Point<string>("1.33.2", "2.22.3", "4.22.1")
const point3: Point<string> = new Point("1.33.2", "2.22.3", "4.22.1")


数组泛型的写法:

// 定义字符串数组
const arr1: string[] = ["a", "b", "c"]			
const arr2: Array<string> = ["a", "b", "c"]

七、泛型约束

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

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

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

interface ILength {
  length: number
}

// 泛型继承接口, 这样传入的泛型类型就必须和ILength接口一样具有length属性才可以
function getLength<T extends ILength>(arg: T) {
  console.log(arg.length)
}

// getLength(123) 			// 123没有length无法传入
getLength("abcdefg") 		// 7
getLength([10, 20, 30, 40]) // 4
getLength({ length: 20 })	// 10

T extends表示传入的类型必须是extends后面的类型或者子类型。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/116468.html

(0)
seven_的头像seven_bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!