一文教你学会使用 ts 泛型;ts 泛型常用知识点


最近回头复习了一下 ts 泛型的知识,做一些笔记的总结分享~

1.泛型是什么?为什么要用泛型?

引用官网的例子,此时有一个需求:我们要定义一个函数,他会返回任何传入他的值。

这个情况下,我们如果已知他的数据类型(假定是 number),就可以写出以下代码:

function echo(val: number): number  {
	return val
}

但如果我们不知道他的类型,那么我们只能使用 any类型

function echo(val: any): any  {
	return val
}

显然,使用any会使我们丢失一些信息,例如我们已经没有办法保证输入输出的值类型相同,因为他们的值都可以是任何类型。

所以这种时候我们就要使用泛型,即类型变量。它是表示类型的变量,而不是一个值。

2.泛型如何使用

在函数名之后写上fn<泛型变量名>,通常泛型名使用大写的 T,当然你可以随意命名,在调用的时候可以在函数名字后面加上fn<泛型类型>

使用泛型后,我们可以这样改写上面的echo函数:

function echo<T>(val: T): T {
    return val;
}

我们给 echo添加了一个类型变量T,这样就能实现在初始类型未知的同时,保证输入输出值的类型相同了。

使用echo函数:

const output = echo<number>(1)

前面我们说到,在调用的时候函数名字后面可以加上<泛型类型>

但有时候,我们没必要使用<>明确的传入类型,编译器可以查看传入的值,来进行自动推断,然后把T自动设置为他的类型。

所以上面的代码可以改写成:

 const output = echo(1)

我们也可以使用不同的泛型参数名,只要在数量上和使用方式上能对应上就可以。

let myEcho: <U>(val: U) => U = echo;

泛型类

泛型类与泛型接口类似:

class GenericNumber<T> {
    zeroValue: T;
    add: (x: T, y: T) => T;
}

let testGenericNumber = new GenericNumber<number>()
testGenericNumber = 0
testGenericNumber.add = function(x, y) {
    return x + y
}

泛型类的使用是非常直观的,上面的例子中,我们限定了T的值为number,当然也可以使用其他类型。

泛型约束

书写泛型的时候,我们往往需要对类型参数做一些约束。此时我们要使用extends关键字。

如下面的例子:

interface Phone {
  phone: string
}

function getPhone<T extends Phone>(val: T): string {
  return val.phone
}

// 使用函数
getPhone({
  name: "小明",
  phone: '',
  age: 10
})

这里写了一个获取手机号的方法,对传入参数的类型做了限制,数组的每一项可以是包含多个属性的对象,但其必须有一个string类型的phone属性

3.泛型部分实用工具类型

  • Exclude

Exclude<T, U>:他的作用是将T里面的U去掉,并返回T,主要用于联合类型。

Exclude的定义是type Exclude <T, U> = T extends U ? never : T

例子:

type A = Exclude<string | number, number> // string
type B = Exclude<'key1' | 'key2', 'key2' | 'key3'> // 'key1'

由定义得原理:

type A = Exclude<string | number, number>
// 等价于
type A = Exclude<string, number> | Exclude<number, number>

// =>
type A = (string extends number ? never : string) | (number extends number ? never : number)

// =>
type A = string | never

// 又因为 never 是所有类型的子类型
type A = string
  • Extract

Extract<T, U>:他的作用与上面的Exclude相反,是将T里面的U取出,并返回,主要用于联合类型。

Extract的定义是type Extract<T, U> = T extends U ? T : never ,可以知道,原理和Exclude一样,只是调换了位置。

例子:

type A = Exclude<'a' | 'b' | 'c', 'a' | 'd'> //'a'
  • Omit

Omit<T, U>:作用是把 T(对象类型) 里边的 U 去掉,并返回 T 里还剩下的。而他和Exclude的区别在于,Exclude多用于联合类型,而Omit多用于处理对象类型

Omit的定义:type Omit <T, K extends keyof any> = { [P in Exclude <keyof T, K>]: T[P] }

例子:

type userInfo = {
	name: string
	age: number
    phone: number
}

type A = Omit<userInfo, 'age'> //type A = { name: string, phone: number }
  • Pick

Pick<T, U>:顾名思义,它的作用是把 T(对象类型) 里边的 U 提取出来并返回,很明显,与Omit呈相反的关系。

Pick的定义:type Pick<T, K extends keyof T> = { [P in K]: T[P] }

其中K extends keyof T则是用来约束K的条件,即,传入K的参数必须是T中有的类型。

类似Omit的例子:

type userInfo = {
	name: string
	age: number
    phone: number
}

type A = Pick<userInfo, 'name' | 'phone'> //type A = { name: string, phone: number }

4.结语

以上是复习 ts 泛型时的笔记心得,如有错误欢迎在评论区指出~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值