【TypeScript】泛型

文章目录

  • 1、介绍
  • 2、泛型函数
    • - 定义泛型
    • - 使用泛型
  • 3、泛型接口
    • 3.1 约束对象形状:
    • 3.2 泛型接口作为函数类型
    • 3.3 泛型接口作为字典的类型
    • 3.4 泛型接口与多个类型参数
  • 4、泛型类
    • 4.1 定义一个泛型类
    • 4.2 定义多个类型参数
  • 5、泛型约束
    • 5.1 定义约束条件
    • 5.2 在泛型约束中使用类型参数
    • 5.3 在泛型里使用类类型
      • - 使用构造签名
      • - 使用类类型的泛型函数
      • - 泛型类和工厂函数

1、介绍

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

语法:
泛型的语法是 <> 里写类型参数,一般可以用 T 来表示
泛型中的 T 就像一个占位符、或者说一个变量,在使用的时候可以把定义的类型像参数一样传入,它可以原封不动地输出

泛型的好处:

  • 函数和类可以轻松地支持多种类型,增强程序的拓展性
  • 不必写冗长的联合类型,增强代码的可读性
  • 灵活控制类型之间的约束

为什么需要泛型?
不使用泛型:

function identity(arg: number): number {return arg;
}function identity(arg: string): string {return arg;
}

或者使用any类型来定义函数:

function identity(arg: any): any {return arg;
}

使用any类型会导致这个函数可以接收任何类型的arg参数,这样就丢失了一些信息:传入的类型与返回的类型应该是相同的
因此,我们需要一种方法使返回值的类型与传入参数的类型是相同的

2、泛型函数

- 定义泛型

function identity<T>(arg: T): T {return arg;
}
// T帮助我们捕获用户传入的类型(比如:number),之后我们就可以使用这个类型

- 使用泛型

定义了泛型函数后,两种方法使用
(1)传入所有的参数,包含类型参数:

let output = identity<string>("myString"); // type of output will be 'string'

(2)利用了类型推论 – 即编译器会根据传入的参数自动地帮助我们确定T的类型:

let output = identity("myString");  // type of output will be 'string'

3、泛型接口

泛型接口允许你在定义接口的时候不具体指明某些类型,并且在实现接口或者使用接口的时候再指定这些类型
泛型接口可以用来约束对象的形状、数组内容、函数签名等多种用途。

3.1 约束对象形状:

定义:

interface Identity<T> {value: T;getMessage(): string;
}

使用:

// 使用接口并指定 T 为 number 类型
let numberIdentity: Identity<number> = {value: 42,getMessage() {return `Value is a number: ${this.value}`;}
};// 使用接口并指定 T 为 string 类型
let stringIdentity: Identity<string> = {value: 'Hello',getMessage() {return `Value is a string: ${this.value}`;}
};

3.2 泛型接口作为函数类型

定义:

interface GenericFn<T> {(arg: T): T;
}

使用:

// 实现接口的函数 - 返回值类型与入参数类型相同
const identity: GenericFn<number> = (arg) => arg;

3.3 泛型接口作为字典的类型

定义:

interface Dictionary<T> {[key: string]: T;
}

使用:

// 字典创建时确定其值应为字符串类型
let keys: Dictionary<string> = {key1: 'value1',key2:'value2',
};// 字典创建时确定其值应为数组类型
let objectList: Dictionary<object[]> = {list1: [{}, {}],list2: [{}, {}, {}]
};

3.4 泛型接口与多个类型参数

定义:

interface Pair<K, V> {key: K;value: V;
}

使用:

let pair: Pair<string, number> = {key: 'age',value: 35
};

4、泛型类

泛型类是具有一个或多个泛型类型参数的类,这些类型参数在类实例化的时候被指定

4.1 定义一个泛型类

定义:

class GenericClass<T> {// property 的类型为 Tvalue: T;// 构造函数参数的类型为 Tconstructor(value: T) {this.value = value;}// 方法返回值的类型为 TgetValue(): T {return this.value;}
}

使用:

// 使用字符串类型实例化类
const stringInstance = new GenericClass<string>('Hello, TypeScript!');
console.log(stringInstance.getValue()); // 输出: Hello, TypeScript!// 使用数字类型实例化类
const numberInstance = new GenericClass<number>(42);
console.log(numberInstance.getValue()); // 输出: 42// 使用数组类型实例化类
const arrayInstance = new GenericClass<string[]>(['apple', 'banana', 'cherry']);
console.log(arrayInstance.getValue()); // 输出: ['apple', 'banana', 'cherry']

4.2 定义多个类型参数

定义:

class KeyValueClass<K, V> {key: K;value: V;constructor(key: K, value: V) {this.key = key;this.value = value;}getKeyValue(): string {return `Key: ${this.key}, Value: ${this.value}`;}
}

使用:

// 使用类
const keyValuePair = new KeyValueClass<number, string>(1, 'One');
console.log(keyValuePair.getKeyValue()); // 输出: Key: 1, Value: One

5、泛型约束

5.1 定义约束条件

定义一个接口来描述约束条件:

//  创建一个包含 .length 属性的接口
interface Lengthwise {length: number;
}// 使用这个接口和extends关键字来实现约束:
function loggingIdentity<T extends Lengthwise>(arg: T): T{return arg;
}

现在这个泛型函数被定义了约束,因此它不再是适用于任意类型:

loggingIdentity(3);  // Error, number doesn't have a .length property

我们需要传入符合约束类型的值,必须包含必须的属性:

loggingIdentity({length: 10, value: 3});

5.2 在泛型约束中使用类型参数

你可以声明一个类型参数,且它被另一个类型参数所约束
定义:

function getProperty<T, K extends keyof T>(obj: T, key: K) {return obj[key];
}

使用:

const obj = {name: 'Alice',age: 25,hasPet: false
};// 正常使用
const name = getProperty(obj, 'name'); // 正确,name 的类型被推断为 string
const age = getProperty(obj, 'age');   // 正确,age 的类型被推断为 number// 错误使用
const weight = getProperty(obj, 'weight');   // 错误!'weight' 不存在于obj类型上

5.3 在泛型里使用类类型

在 TypeScript 中利用泛型来使用类类型,你可以创建一个函数,其参数或返回值的类型可以是一个类构造器(类的静态部分)或类的实例(类的实例部分)

- 使用构造签名

function createInstance<T>(c: { new (): T }): T {return new c();
}

- 使用类类型的泛型函数

例如,假设我们有一个类 Animal 和一个工厂函数,我们想让这个函数返回一个 Animal 类型的实例对象:

class Animal {name: string;constructor(name: string) { this.name = name; }move(meters: number) {console.log(`${this.name} moved ${meters}m.`);}
}// createInstance 函数可以接受任何具有单个字符串参数构造函数的类
function createInstance<T>(c: { new (name: string): T }): T {return new c('Animal Name');
}let animal: Animal = createInstance(Animal);
animal.move(5); // 输出: Animal Name moved 5m.

- 泛型类和工厂函数

你也可以在泛型类中使用类类型,如下所示:

class BeeKeeper {hasMask: boolean = true;
}class ZooKeeper {nameTag: string = 'Mikle';
}class Animal {numLegs: number = 4;
}class Bee extends Animal {keeper: BeeKeeper = new BeeKeeper();
}class Lion extends Animal {keeper: ZooKeeper = new ZooKeeper();
}function createInstance<A extends Animal>(c: new () => A): A {return new c();
}// 创建 Lion 实例
createInstance(Lion).keeper.nameTag;  // 类型检查 OK
// 创建 Bee 实例
createInstance(Bee).keeper.hasMask;   // 类型检查 OK

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/603091.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue中的组件通信方式及应用场景

在Vue中&#xff0c;组件通信有以下几种方式&#xff1a; Props / $emit&#xff1a;父组件通过给子组件传递props属性&#xff0c;子组件通过$emit事件将数据传递给父组件。适用于父组件向子组件传递数据。 自定义事件&#xff1a;父组件通过$on监听子组件触发的事件&#xf…

数据链路层(Data Link Layer)

数据链路层&#xff08;Data Link Layer&#xff09;是计算机网络体系结构中的一层&#xff0c;位于物理层和网络层之间。它的主要功能是在物理传输媒体上建立和管理数据链路。数据链路层的设计和实现对于网络通信的可靠性和效率至关重要。在本文中&#xff0c;我们将探讨数据链…

C#-接口

接口 (interface) 定义了一个可由类和结构实现的协定。接口可以包含方法、属性、事件和索引器。接口不提供它所定义的成员的实现 — 它仅指定实现该接口的类或结构必须提供的成员。 接口可支持多重继承。在下面的示例中&#xff0c;接口 IComboBox 同时从 ITextBox 和 IListBox…

IIS+SDK+VS2010+SP1+SQL server2012全套工具包及安装教程

前言 今天花了两个半小时安装这一整套配置&#xff0c;这个文章的目标是将安装时间缩短到1个小时 正文 安装步骤如下&#xff1a; VS2010 —> service pack 1 —>SQL server2012 —> IIS —> SDK 工具包链接如下&#xff1a; https://pan.baidu.com/s/1WQD-KfiUW…

[技术杂谈]使用VLC将视频转成一个可循环rtsp流

通过vlc播放器&#xff0c;将一个视频转成rtsp流&#xff0c;搭建一个rtsp服务器。rtsp客户端可访问这个视频的rtsp流。 1. 打开vlc播放器&#xff0c;使用的版本如下 2. 菜单&#xff1a;媒体 ---> 流 3. 添加视频文件&#xff0c;点击添加一个mp4 文件 4. 选择串流&…

如何安装和使用夜神模拟器连接Android Studio

目录 简介 一、安装 二、使用 三、更多资源 简介 夜神模拟器是一款在Windows平台上运行的Android模拟器软件。它能够模拟Android操作系统环境&#xff0c;让用户在电脑上轻松体验Android应用程序。夜神模拟器的功能强大&#xff0c;可以满足各种需求&#xff0c;无论是娱乐…

故障诊断 | 基于FFT频谱与小波时频图的双流CNN轴承故障诊断模型(matlab +python)

目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 故障诊断 | 基于FFT频谱与小波时频图的双流CNN轴承故障诊断模型&#xff08;matlab python&#xff09; 基于FFT频谱与小波时频图的双流CNN轴承故障诊断模型 特征拼接 python&#xff08;pytorch&#xff09; 基于2D-…

可视化速通知识点

本文仅仅是我对可视化主要知识的一些记忆与思考&#xff0c;欢迎大家学习与批评指正。 首先&#xff0c;什么是可视化&#xff1f;可视化是利用计算机图形学和图像处理技术&#xff0c;将数据在屏幕上显示出来&#xff0c;并使用交互式处理的方法、理论和技术。 可视化的基本流…

大模型迎来“AppStore时刻”,OpenAI给2024的新想象

一夜之间&#xff0c;OpenAI公布了多个重磅消息&#xff0c;引发市场关注。 钛媒体App 1月5日消息&#xff0c;今晨&#xff0c;OpenAI公司向所有GPT开发者们发布一封邮件称&#xff0c;下周将上线自定义的“GPT Store”商店&#xff0c;这有望推动ChatGPT开发者生态不断完善。…

开源加解密库之GmSSL

一、简介 GmSSL是由北京大学自主开发的国产商用密码开源库&#xff0c;实现了对国密算法、标准和安全通信协议的全面功能覆盖&#xff0c;支持包括移动端在内的主流操作系统和处理器&#xff0c;支持密码钥匙、密码卡等典型国产密码硬件&#xff0c;提供功能丰富的命令行工具及…

多线程高级知识点

多线程高级知识点 1.ThreadLocal 1.1 什么是 ThreadLocal&#xff1f; ​ ThreadLocal 叫做本地线程变量&#xff0c;意思是说&#xff0c;ThreadLocal 中填充的的是当前线程的变量&#xff0c;该变量对其他线程而言是封闭且隔离的&#xff0c;ThreadLocal 为变量在每个线程…

服务器运维管理面板1Panel本地部署并结合内网穿透实现远程访问

文章目录 前言1. Linux 安装1Panel2. 安装cpolar内网穿透3. 配置1Panel公网访问地址4. 公网远程访问1Panel管理界面5. 固定1Panel公网地址 前言 1Panel 是一个现代化、开源的 Linux 服务器运维管理面板。高效管理,通过 Web 端轻松管理 Linux 服务器&#xff0c;包括主机监控、…

EtherCAT主站SOEM -- 13 --Qt-Soem通过界面按键控制 EtherCAT IO模块的io输出

EtherCAT主站SOEM -- 13 --Qt-Soem通过界面按键控制 EtherCAT IO模块的io输出 一 mainwindow.c 文件函数:1.1 自定义PDO配置2.2 主站初始化2.3 去motrorcontrol界面二 motrorcontrol.c 文件三 allvalue.h 文件该文档修改记录:总结一 mainwindow.c 文件函数: mainwindow主界…

Docker学习与应用(四)-容器数据卷

1、容器数据卷 1&#xff09;什么是容器数据卷 docker的理念回顾 将应用和环境打包成一个镜像&#xff01; 数据&#xff1f;如果数据都在容器中&#xff0c;那么我们容器删除&#xff0c;数据就会丢失&#xff01;需求&#xff1a;数据可以持久化 MySQL&#xff0c;容器删…

MYSQL 存储过程/存储函数

简而言之&#xff0c;类似于封装函数 特点 基本语法 create peocedure p1() begin select coun(*) from studuent; end; call p1(); 设置完别忘了把delimiter改回来 变量 系统变量 用户自定义变量 set myname its; set myage : 10; 局部变量 if 参数&#xff08;IN&…

Oracle VM VirtualBox xx needs the Micrsoft Visual C++ 2019错误

错误展示 解决方法 重修安装 Visual C 文件 1、前往官网 C 中 Windows 编程概述 | Microsoft Learn 2、找到对应的包 左边导航栏依次选择&#xff1a; 部署本机桌面应用程序-----重新分发Visual C 文件-----最新受支持的Visual C可再发型程序包下载 根据自己电脑系统进行选…

linux mv command and authority managemet

mv abbreviation for move, as to move files and folders or change the folder name/ rename the specific folderLinux常见权限解释 -rw------- (600) 只有拥有者有读写权限。 -rw-r–r-- (644) 只有拥有者有读写权限&#xff1b;而属组用户和其他用户只有读权限。 -rwx--…

私域运营常用的ChatGPT通用提示词模板

私域流量获取&#xff1a;如何获取更多的私域流量&#xff0c;提高用户粘性和转化率&#xff1f; 私域用户画像&#xff1a;如何建立私域用户的画像&#xff0c;了解用户需求和行为习惯&#xff1f; 私域内容运营&#xff1a;如何制定有效的私域内容策略&#xff0c;提高用户…

mybatis和Hibernate对比

MyBatis和Hibernate是两个在Java开发中常用的持久化框架&#xff0c;它们有以下区别&#xff1a; 1. ORM vs. SQL映射&#xff1a; - Hibernate是一个全功能的ORM&#xff08;对象关系映射&#xff09;框架&#xff0c;它将Java对象与数据库表之间的映射关系进行管理&#xff0…

Python 教程 02:Python 编程环境的搭建与 IDE 的选择

目录 一、搭建 Python 环境 1.1 Python 官网 1.2 下载 Python 1.2.1 选择版本 1.2.2 选择平台 1.2.3 下载安装文件&#xff08;Windows & macOS&#xff09; 1.3 安装环境 1.3.1 Windows 平台 1.3.2 macOS 平台 1.3.3 Linux 平台 1.4 验证安装是否成功 二、选择…