首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >typescript基础篇(6):泛型

typescript基础篇(6):泛型

作者头像
一粒小麦
发布2020-08-17 16:29:43
9640
发布2020-08-17 16:29:43
举报
文章被收录于专栏:一Li小麦一Li小麦

6.泛型

软件工程中,我们不仅要创建一致的定义良好的API,同时也要考虑可重用性。组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,在定义函数,接口或类的时候,不预先指定类型,而是等到使用时才指定——这在创建大型系统时为你提供了十分灵活的功能。

在TypeScript中,可以使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据。这样用户就可以以自己的数据类型来使用组件。

6.1 泛型的场景

举例说,一个打印函数:

const log = (value: string): string => {
  console.log(value)
  return value
}

如果我希望这个函数能接收字符串参数,又能接收字符串数组参数。应当如何实现呢?

现在有两种解决方式:我们已经函数重载,联合类型。

// 1. 函数重载
function log(value: string): string
function log(value: string[]): string[]
function log(value: any): any {
  if (typeof value == "string") {
    console.log(value)
  } else if (Array.isArray(value)) {
    value.forEach((item) => console.log(item))
  }
  return value
}
log("aaa")
log(["bbb", "ccc"])


// 2. 联合类型 相对简洁
const log = (value: string | string[]): string | string[] => {
  if (typeof value == "string") {
    console.log(value)
  } else if (Array.isArray(value)) {
    value.forEach((item) => console.log(item))
  }
  return value
}

log("aaa")
log(["bbb", "ccc"])

但是以上实现不管哪一种,都有重大问题:我们无论用any还是用联合类型:都忽略了入参必须和返回值类型一致。

这时的最好解决方案就是泛型。接下来就改造下:

const log = <T>(value: T): T => {
  console.log(value)
  return value
}

改造之后,T不需要预先指定,也可以准确反映参数和返回值的关系。

6.2 泛型函数调用

泛型函数有两种调用方式:

log("aaa")
log<string[]>(["aaa", "bbb"])

不仅可以用泛型定义函数还可以定义泛型函数类型,格式和函数签名差不多:

const log = <T>(value: T): T => {
  console.log(value)
  return value
}

type Log = <T>(value: T) => T
const myLog: Log = log

6.3 泛型接口

泛型接口:

interface Log {
  <T>(value: T): T
}

当你吧<T>放到Log后面,接口的所有成员都会收到<T>的约束

interface Log<T> {
  (value: T): T
}
// const myLog: Log = log //报错:需要指定类型参数
const my_log: Log<number> = log
my_log(1) // my_log只接收数字

6.4 泛型类

泛型类看上去与泛型接口差不多。泛型类使用( <>)括起泛型类型,跟在类名后面。

class Log<T> {
  run(value: T) {
    console.log(value)
  }
}

const log1 = new Log<number>()
log1.run(1)

// 不指定方法, 传入的是任意的值。
const log2 = new Log()

注意,泛型不得用于静态成员(static声明的成员)

6.5 类型约束

有时候我们会希望实现类似这样的功能:

const log = <T>(value: T): T => {
  console.log(value, value.length)
  return value
} // 执行报错

允许传入一个任意类型的参数,还要可以打印length属性。这种逻辑别说在ts,在js也算不得很好的实践。

这时,就需要类型约束。我们定一个length接口,表示定义了一个包含length属性的类型,然后让泛型参数继承这个接口:

interface Length {
  length: number
}

const log = <T extends Length>(value: T): T => {
  console.log(value, value.length)
  return value
}

这时候的泛型T就不是什么都能传了。能传的包括数组,字符串,{length:number等}

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-08-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 一Li小麦 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 6.泛型
    • 6.1 泛型的场景
      • 6.2 泛型函数调用
        • 6.3 泛型接口
          • 6.4 泛型类
            • 6.5 类型约束
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档