TypeScript学习 | 泛型

简介

泛型是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性

作用

可以保证类型安全的前提下,让函数、接口或类与多种类型一起工作,从而实现复用

基本使用

举个例子:

创建一个id函数、该函数传入什么数据就返回数据本身,也就是参数和返回值类型相同。

typescript 复制代码
function id(value:number): number {
  return value
}

id<number>(99) // 99
typescript 复制代码
function id(value:string): string {
  return value
}

id<string>('hhh') // hhh

综上所述、上面两个函数接收的类型是写死的,只能传入相应的数据类型,为了能让函数接口任意类型吗,可以将参数类型改为any。但是这样就失去TS的类型保护,类型不安全。

这时候,泛型就能派上用场了。

typescript 复制代码
function id<T>(value:T):T {
  return value
}

id<number>(99) // 99
id<string>('hhh') // hhh
id<number[]>([1,2,3]) // [1,2,3]
  • 在函数名称的后面添加<>,其中尖括号里面的T就是类型参数,它用来处理类型而不是值,它可以是任意合法的变量名称
  • 因为T是类型,因此可以将T作为参数和返回值的类型,表示参数和返回值具有相同的类型
  • 由于TS内部会采用一种叫做类型参数推断的机制,来根据传入的数据推断出相对应的类型,针对一些基础数据类型,可以省略不写。比如上述 id<number>(99)可直接写成id(99)id<string>('hhh')可简单写成id('hhh')。当编译器无法推断类型或者推断的类型不准确时,就需要显式的传入类型参数。比如id<number[]>([1,2,3])

单个类型参数 VS 多个类型参数

单个类型参数

typescript 复制代码
function id<T>(value:T):T {
  return value
}
id<number>(99) // 99

顾名思义:类型参数只有一个,如上,只有一个 T

多个类型参数

typescript 复制代码
function swap<T, U>(value: [T, U]): [U, T] {
    return [value[1], value[0]];
}

swap([18, 'age']); // ['age', 18]

多个类型参数之间可进行相互约束

多类型变量之间还可以进行约束,比如第二个类型变量所第一个类型变量约束。

javascript 复制代码
function getPro<T, K extends keyof T> (obj:T, key:K) {
 return obj[[key]
}

getPro({name:'abc',age:18},'age')
getPro('abc','length')
getPro([a,b,c],'length')
  • keyof 接收一个对象类型,生成其键名称或数字的联合类型
  • 类型K受类型T的约束,上述可以理解为K只能是T中所存在的键中任意一个,或者说只能访问对象中存在的属性。

泛型约束

在函数内部使用泛型变量的时候,由于事先不知道它是哪种类型,所以导致无法访问它的属性和方法。如下:

javasript 复制代码
function id<T>(value:T):T {
  console.log(value.length) //这段代码编译器会报错:Property 'length' does not exist on type 'T'. 
  return value
} 

上述代码中无法保证传入的数据一定存在length属性。所以,就需要为泛型添加约束。(只允许这个函数传入那些包含 length 属性的变量)

指定更加具体的类型

javasript 复制代码
function id<T>(value:T[]):T[] {
  console.log(value.length)  
  return value
} 

如上、可将T改成T[],也就是T类型的数组,这样数组就一定存在lengh属性,就可以正常访问了。

使用 extends 添加约束

javascript 复制代码
interface TLength {
  length:number
}

function id<T extends TLength>(value:T): T {
   console.log(value.length)  
   return value
}


id(['xxx','yyy'])
id('hhhhh')
id({length:10,name:'abcd'})
  • 创建描述约束的接口TLength,该接口提供length属性
  • 通过extends关键字使用该接口,为泛型添加约束。

泛型接口

接口也可以配合泛型使用

泛型类

泛型工具类型

Partial<Type>

用来创建一个类型,将Type中的所有属性都设置为可选

Readonly<Type>

用来创建一个类型,将Type中的所有属性都设置为只读

Pick<Type,Keys>

从Type中选择一组属性来构造新类型

Record<Keys,Type>

构造一个对象类型,属性键为Keys,属性类型为Type

相关推荐
前端卧龙人1 分钟前
这个浏览器空闲API性能优化,你一定要知道~
前端
赵晟鼎2 分钟前
node常用fs文件操作方法
前端·javascript·node.js
女生也可以敲代码2 分钟前
如何使用 qrcode.react生成二维码
前端·react.js·typescript
关山月27 分钟前
理解 HTTP 响应和流
前端
拖孩37 分钟前
微信小程序基于Canvas实现头像图片裁剪(下)
前端·javascript·微信小程序
哟哟耶耶1 小时前
React-05React中props属性(传递数据),propTypes校验,类式与函数式组件props的使用
前端·javascript·react.js
前端菜鸟日常1 小时前
前端性能优化核弹级方案:CSS分层渲染+Wasm,首屏提速300%!
前端·css·性能优化·wasm
竹苓丿1 小时前
CSS Grid布局:从入门到放弃再到真香
前端·javascript·css
广龙宇1 小时前
【Web API系列】WebSocketStream API 深度实践:构建高吞吐量实时应用的流式通信方案
前端
好_快2 小时前
Lodash源码阅读-isFlattenable
前端·javascript·源码阅读