第五章 TypeScript泛型的介绍和使用

image.png

一、泛型

初识泛型

  • 一个函数,需要参数是 number 数据类型,返回值也是 number 数据类型
function fn(arg: number): number { 
  // 代码忽略不计 
}
  • 又一个函数,需要参数是 string 类型,返回值也是 string 数据类型
function fn(arg: string): string {
  // 代码忽略不计
}
  • 我们发现,我们给函数的参数和返回值都进行了限制
    • 假设,如果两段代码的业务逻辑一样
    • 我们可以不可把两个函数写成一个
    • 需求:我传递的是 数字,返回值就是数字,传递的是 字符串,返回值就是 字符串
  • 思考过后,我们想到可以用 或( | )
function fn(arg: number | string): number | string {
  // 代码忽略不计
}
  • 看起来不错
  • 但是不能完全满足我们的需求
    • 参数 number 返回值 number
    • 参数 number 返回值 string
    • 参数 string 返回值 number
    • 参数 string 返回值 string
  • 以上四种情况都是可以的
  • 和我们预期的需求不一样
  • 我也可以写成 any 类型不就好了
function fn(arg: any): any { 
  // 代码忽略不计 
}
  • 这样一来,好像对参数和返回值的限制又都没有了
  • 那么 TS 的意义好像不大了
  • 难道说用了 TS 以后,我们的代码反而不灵活了吗 ?
  • 来看下面一段代码
function fn<T>(arg: T): T { 
  // 代码忽略不计 
}
  • 这个玩意看起来怪怪的,感觉认识但又不完全认识
  • 这里函数名后面的 “” 表示给该函数定义了一个泛型,就是预设了一个类型限制
  • 将来你调用这个函数的时候,来传递一个类型对函数进行约束
// 用 string 去填充预设
// 当前函数的参数必须是 string,返回值也必须是 string
fn<string>('hello')

// 用 number 去填充预设
// 当前函数的参数必须是 number,返回值也必须是 number
fn<number>(100)
  • 在来思考我们一开始的需求,其实主要就是取决于调用的时候
  • 泛型,其实就是在定义阶段不预先指定具体类型,只是留下一个空位或者预设位置,当你使用的时候在决定使用什么具体的数据类型填充

泛型用法

  1. 函数泛型
    • 就是利用泛型限定函数的参数和返回值
function test <T>(arg: T): T{
  // ... 此处省略代码 10000 行
  return arg
}
test<number>(111) // 返回值是 number 类型
  • 也可以设置多个泛型标识符
function test <T, U>(arg1: T,arg2: U): [UT]{
  // ... 此处省略代码 10000 行
  return [ arg2,arg1 ]
} 
test<numberstring>(100'hello world')
  • 泛型标识符可以设置一个,也可以设置多个,用哪个字母无所谓
  1. 接口泛型
    • 在定义接口的时候,也可以使用泛型
interface User<T> {
  gender: T
}

const p1: User<string> = {
  gender: '男'
}

const p2: User<boolean> = {
  gender: true
}
  • 这样看起来,泛型是不是非常方便呢
  • 同样,也可以设置一个,也可以设置多个
// 制作一个方法的接口泛型
interface Search {
  <T, Y>(name: T, age: Y): T
  }

let fn:Search = function <TY>(name: T, id: Y): T {
  // ... 此处省略代码 10000 行
  return name;
}
  1. 类泛型
    • 在定义类的时候,我们也可以加入一些泛型限制一些内容
class Animal<T> {
  name: T
  constructor(name: T){
    this.name = name
  }
  action<T>(say: T) {
    console.log(say)
  }
}
let cat = new Animal<string>('千锋大前端')
cat.action<string>('Hello,欢迎来到千锋大前端')

二、断言

  • 断言是一个非常有意思的小玩意,有的时候可以在我无助的时候给我带来一丝希望
  • 我一直觉得断言就是 “奥特曼”

image.png

  • 看一个例子
// 获取了一个页面上的 div 元素
const ele = document.querySelector('div')

// 制作一个简单的功能函数,要求参数接受一个 DIV 元素
function util(ele: HTMLDivElement): void {}

// 调用函数传入参数
util(ele)
  • 在正常不过的一段代码了,这个有啥的
  • 写完我们才发现

image.png

  • 为什么 ? 为什么 ?

image.png

  • 会不会是因为我定义 ele 变量的时候,没有限制类型呢

image.png

  • 这回下面好了,上面又出问题了
  • 解释一下吧
    • 其实是因为,我们获取元素这个操作,是有可能获取不到的
    • 当我们获取不到的时候就是 null
    • 就不是 HTMLDivElement 这个类型了
    • 所以在哪个地方限制好以后,都会出现问题的
  • 怎么办呢,这个时候,就可以使用断言了
  • 断言其实就是我主观给他强制定义一个类型,这样就不会出现问题了
const ele = document.querySelector('div') as HTMLDivElement

function util(ele: HTMLDivElement): void {}

util(ele)
  • 这里我就强制把 ele 元素断定为 HTMLDivElement 类型,那么就不会出现问题了
  • 其实在很多时候,我们不确定,或者拿不准的时候,我们都可以使用断言来解决问题
  • 先不让他报错,O(∩_∩)O~
  • 剩下的后面再说
  • 20
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杨树林er

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值