一、是什么

泛型程序设计(generic programming)是程序设计语言的一种风格或范式

泛型允许我们在强类型程序设计语言中编写代码时使用一些以后才指定的类型,在实例化时作为参数指明这些类型 在typescript中,定义函数,接口或者类的时候,不预先定义好具体的类型,而在使用的时候在指定类型的一种特性

假设我们用一个函数,它可接受一个 number 参数并返回一个number 参数,如下写法:

function returnItem (para: number): number {
    return para
}

如果我们打算接受一个 string 类型,然后再返回 string类型,则如下写法:

function returnItem (para: string): string {
    return para
}

上述两种编写方式,存在一个最明显的问题在于,代码重复度比较高

虽然可以使用 any类型去替代,但这也并不是很好的方案,因为我们的目的是接收什么类型的参数返回什么类型的参数,即在运行时传入参数我们才能确定类型

这种情况就可以使用泛型,如下所示:

function returnItem<T>(para: T): T {
    return para
}

可以看到,泛型给予开发者创造灵活、可重用代码的能力

二、使用方式

泛型通过<>的形式进行表述,可以声明:

  • 函数

  • 接口

函数声明

声明函数的形式如下:

function returnItem<T>(para: T): T {
    return para
}

定义泛型的时候,可以一次定义「多个类型参数」,比如我们可以同时定义泛型 T 和 泛型 U

function swap<T, U>(tuple: [T, U]): [U, T] {
    return [tuple[1], tuple[0]];
}

swap([7, 'seven']); // ['seven', 7]

接口声明

声明接口的形式如下:

interface ReturnItemFn<T> {
    (para: T): T
}

那么当我们想传入一个number作为参数的时候,就可以这样声明函数:

const returnItem: ReturnItemFn<number> = para => para

类声明

使用泛型声明类的时候,既可以作用于类本身,也可以作用于类的成员函数

下面简单实现一个元素同类型的栈结构,如下所示:

class Stack<T> {
    private arr: T[] = []

    public push(item: T) {
        this.arr.push(item)
    }

    public pop() {
        this.arr.pop()
    }
}

使用方式如下:

const stack = new Stacn<number>()

如果上述只能传递 string 和 number 类型,这时候就可以使用 <T extends xx> 的方式猜实现「约束泛型」,如下所示:

除了上述的形式,泛型更高级的使用如下:

例如要设计一个函数,这个函数接受两个参数,一个参数为对象,另一个参数为对象上的属性,我们通过这两个参数返回这个属性的值

这时候就设计到泛型的索引类型和约束类型共同实现

索引类型、约束类型

索引类型 keyof T 把传入的对象的属性类型取出生成一个联合类型,这里的泛型 U 被约束在这个联合类型中,如下所示:

function getValue<T extends object, U extends keyof T>(obj: T, key: U) {
  return obj[key] // ok
}

上述为什么需要使用泛型约束,而不是直接定义第一个参数为 object类型,是因为默认情况 object 指的是{},而我们接收的对象是各种各样的,一个泛型来表示传入的对象类型,比如 T extends object

使用如下图所示:

多类型约束

例如如下需要实现两个接口的类型约束:

interface FirstInterface {
  doSomething(): number
}

interface SecondInterface {
  doSomethingElse(): string
}

可以创建一个接口继承上述两个接口,如下:

interface ChildInterface extends FirstInterface, SecondInterface {

}

正确使用如下:

class Demo<T extends ChildInterface> {
  private genericProperty: T

  constructor(genericProperty: T) {
    this.genericProperty = genericProperty
  }
  useT() {
    this.genericProperty.doSomething()
    this.genericProperty.doSomethingElse()
  }
}

通过泛型约束就可以达到多类型约束的目的

三、应用场景

通过上面初步的了解,后述在编写 typescript 的时候,定义函数,接口或者类的时候,不预先定义好具体的类型,而在使用的时候在指定类型的一种特性的时候,这种情况下就可以使用泛型

灵活的使用泛型定义类型,是掌握typescript 必经之路

TypeScript 中泛型的理解?应用场景?的更多相关文章

  1. Typescript中一些不理解的概念解释(泛型、断言、解构、枚举)

    新的项目想使用typescript,因此又对其概念及使用过一遍,本文主要记录下对之前一些概念不太理解的地方. 1.泛型 定义: 在定义函数.接口或者类的时候,不预先指定具体的类型,而是在使用的时候再指 ...

  2. Java中泛型的理解

    Java中的泛型,本质上来说,就是是参数化类型,就是说所操作的数据类型被指定为一个参数,而不是确定的某种类型.这种数据类型可以用在类.接口和方法创建中.即泛型类.泛型接口.泛型方法.这样说可能不够生动 ...

  3. TypeScript 中函数的理解?与 JavaScript 函数的区别?

    一.是什么 函数是JavaScript 应用程序的基础,帮助我们实现抽象层.模拟类.信息隐藏和模块 在TypeScript 里,虽然已经支持类.命名空间和模块,但函数仍然是主要定义行为的方式,Type ...

  4. 十分钟教你理解TypeScript中的泛型

    转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者.原文出处:https://blog.bitsrc.io/understanding-generics-in-t ...

  5. Java 泛型 <? super T> 中 super 怎么 理解?与 < ? extends T>有何不同?

    Java 泛型 <? super T> 中 super 怎么 理解?与 extends 有何不同? 简介 前两篇文章介绍了泛型的基本用法.类型擦除以及泛型数组.在泛型的使用中,还有个重要的 ...

  6. typescript 中的 infer 关键字的理解

    infer 这个关键字,整理记录一下,避免后面忘记了.有点难以理解呢. infer infer 是在 typescript 2.8中新增的关键字. infer 可以在 extends 条件类型的字句中 ...

  7. TypeScript 中命名空间与模块的理解?区别?

    一.模块 TypeScript 与ECMAScript 2015 一样,任何包含顶级 import 或者 export 的文件都被当成一个模块 相反地,如果一个文件不带有顶级的import或者expo ...

  8. TypeScript Generics(泛型)

    软件工程的一个主要部分就是构建组件,构建的组件不仅需要具有明确的定义和统一的接口,同时也需要组件可复用.支持现有的数据类型和将来添加的数据类型的组件为大型软件系统的开发过程提供很好的灵活性. 在C#和 ...

  9. 【TypeScript】如何在TypeScript中使用async/await,让你的代码更像C#。

    [TypeScript]如何在TypeScript中使用async/await,让你的代码更像C#. async/await 提到这个东西,大家应该都很熟悉.最出名的可能就是C#中的,但也有其它语言也 ...

  10. TypeScript 中的方法重载

    方法重载(overload)在传统的静态类型语言中是很常见的.JavaScript 作为动态语言, 是没有重载这一说的.一是它的参数没有类型的区分,二是对参数个数也没有检查.虽然语言层面无法自动进行重 ...

随机推荐

  1. vscode 翻译插件推荐 Easy Translator,只因为有音标,和位置好

    vscode 翻译插件推荐 Easy Translator,只因为有音标,和位置好

  2. docker 资料整理

    docker 资料整理 基础概念 docker deamon 守护系统:简单理解就是docker的软件系统,管控这容器的开关. docker容器:从镜像启动到内存中形成动态运行,从编程角度,如果镜像是 ...

  3. buntu之命令行模式和图形界面切换

    1.按ALT+CTRL+F1切换到字符界面(Linux实体机)      如果是VMware虚拟机安装的Linux系统,则切换到字符界面的时候需要以下操作      按下ALT+CTRL+SPACE( ...

  4. AQS很难,面试不会?看我一篇文章吊打面试官

    AQS很难,面试不会?看我一篇文章吊打面试官 大家好,我是小高先生.在这篇文章中,我将和大家深入探索Java并发包(JUC)中最为核心的概念之一 -- AbstractQueuedSynchroniz ...

  5. github 镜像地址

    亲测可用的 github 镜像地址: https://hub.nuaa.cf , https://hub.fgit.cf

  6. 基于VS Code的JSDoc的使用指南

    1. 引言 JSDoc是一个用于 JavaScript 的API文档生成器,可以将文档注释直接添加到源代码中,JSDoc 工具将扫描您的源代码并提供一些操作,例如,生成一个 API 文档 JSDoc官 ...

  7. PHP 数据库表单创建方法记录(储存三方接口数据必用)

    最近项目在对接第三方接口数据,这里分享下我用来偷懒的一个PHP方法: /** * 数据库表单创建方法 * @return string * @throws \Exception */ public f ...

  8. Jmeter前言

    前言 为什么要撰写这样一个教程呢? 深入学习Jmeter 温故而知新.尽管我已经使用JMeter很长时间,但还有许多元件我并不十分了解,因此,编写教程的过程成为了我的学习过程,通过反复回顾和整理知识, ...

  9. 补充--关于nginx服务器多个网站如何设置404的问题?

    补充--关于nginx服务器多个网站如何设置404的问题? 需求1 :设置多个网站404页面为一个 都需配置网站的nginx.conf,以上面的多网站为例,404发布目录下,每个的nginx.conf ...

  10. SpringBoot项目 填充Excel模板 导出 下载

    模板 下载后的效果 项目结构 pom <?xml version="1.0" encoding="UTF-8"?> <project xmln ...