TypeScript 关于对【泛型】的定义使用解读

目录

    • 概念导读
    • 泛型函数
    • 多个泛型参数
    • 泛型约束
    • 泛型别名
    • 泛型接口
    • 泛型类
    • 总结:


概念导读

泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。使用泛型 可以复用类型并且让类型更加灵活

在这里插入图片描述
泛型实现类型参数化:

在定义这个函数时, 我不决定这些参数的类型
而是让调用者以参数的形式告知,我这里的函数参数应该是什么类型
把类型作为参数,放在尖括号中

泛型的基本使用

案例讲解:

当我们封装一个函数的时候,可能由于业务需求的不同,向函数内,传递的参数类型也不相同。而TS 的语法规范是,在函数定义的时候就需要为每个待接收的形参以及函数的返回值指定类型,如果在我们调用执行函数之前,就将类型给指定死了的话,这就大大降低了,函数的复用性了。


这时候,就可以使用 泛型,来实现这样的需求,将函数所需参数的类型,延后到,当我调用函数的时候,可以根据不同的业务需求再指定其参数类型。这样一来,将大大的提高函数的复用灵活性。


如下案例:

泛型函数

普通函数定义法

function createArray<T>(length: number, value: T): Array<T> {
    let result: T[] = [];
    for (let i = 0; i < length; i++) {
        result[i] = value;
    }
    return result;
}

createArray(3, 'x'); // ['x', 'x', 'x']

箭头函数定义法

let append = <T>(val: T, num: number): Array<T> => {
    const arr: T[] = []
    for (let index = 0; index < num; index++) {
        arr.push(val)
    }
    return arr;
}
console.log(append<string>("一段字符串", 9));
//['一段字符串', '一段字符串', '一段字符串', '一段字符串', '一段字符串', '一段字符串', '一段字符串', '一段字符串', '一段字符串']
console.log(append<number>(10086, 9));
//[10086, 10086, 10086, 10086, 10086, 10086, 10086, 10086, 10086]

我们在函数名后添加了 < T >,其中 T 用来指代任意输入的类型(泛型),后面的参数类型,以及函数返回值的类型,都可以 使用 T 泛型来定义站位。
console.log(append< string >("一段字符串", 9)); 在函数调用的时候再为其指定泛型所具体代表的类型,也可以不手动指定,而让类型推论自动推算出来(推荐手动指定,使其代码更加清晰明了)


多个泛型参数

定义泛型的时候,可以一次定义多个类型参数,同样的在调用的时候再为其指定参数类型,多泛型参数多用于元组类型的数据处理

普通函数写法:

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

console.log(swap<number, string>([7, 'seven']));

箭头函数写法:

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

console.log(swap<string, number>(["字符串", 100]));

泛型约束

由于泛型,表示数据的类型的待定的,由于事先不知道它是哪种类型,所以不能够随意操作一个待定数据类型身上的方法属性,如果传进来的数据类型没有这个属性方法,则就会引起报错。

如下案例:

function loggingIdentity<T>(arg: T): T {
    console.log(arg.length);
    return arg;
}

// 报错:  index.ts(2,19): error TS2339: Property 'length' does not exist on type 'T'.

上例中,泛型 T 不一定包含属性 length,所以编译的时候报错了。

这时候,我们就可以通过接口对泛型进行约束,只允许这个函数传入那些包含 length 属性的变量。这就是泛型约束:

interface Lengthwise {
    length: number;
}

function loggingIdentity<T extends Lengthwise>(arg: T): T {
    console.log(arg.length);
    return arg;
}

上例中我们使用了 extends 约束了泛型 T 必须符合接口 Lengthwise 的形状,也就是必须包含 length 属性。

此时如果调用 loggingIdentity 函数的时候,传入的 arg 数据类型身上 不包含 length 属性,那么在编译阶段就会报错了,这样一来就大大降低了,会发生在函数体内部的错误了

补充

多个类型的参数之间也可以互相约束

function copyFields<T extends U, U>(target: T, source: U): T {
    for (let id in source) {
        target[id] = (<T>source)[id];
    }
    return target;
}

let x = { a: 1, b: 2, c: 3, d: 4 };

copyFields(x, { b: 10, d: 20 });

上例中,我们使用了两个类型参数,其中要求 T 继承 U,也相当于,U 约束了 T ,这样就保证了 U 上不会出现 T 中不存在的字段。


泛型别名

在类型别名 type 的后面使用<T>即可声明一个泛型参数,接口里的其他成员都能使用该参数的类型

type len = {
    length: number
}

let fun = <T extends len>(x: T): number => {
    return x.length
}
console.log(fun<string>("486789413"));//9

泛型接口

前面提到过, interface 是我们在使用 TypeScript 的时候,用来定义接口的关键字。

如:

interface Person {
  name: string;
  age: number;
}
const dome: Person = {
  name: "sunny",
  age: 18,
};

上面示例的代码中用声明接口限制了一个对象,我们也可以通过泛型对我们的接口进行改造

在这里插入图片描述

这时候我们通过定义泛型的方式,定义 T ,U 两个占位符,使得我们的接口具备了泛型,更加灵活。但是我们发现 泛型接口和泛型函数不一样,像上图中这样使用,有一个地方报错了,提示我们需要传入类型参数,而不能依赖自动的类型推断,来确实对象属性的类型,其实这也是可以理解,因为我们对一个对象的限制,主要就是限制对象的属性类型,如果我们不确定类型,那我们传入的一切类型都是有效的了。就起不到类型的限制,而前面我们使用泛型函数,虽然没有显示声明类型,但是我们达到了对函数入参和出参进行了统一。

interface Person<T, U> {
    name: T;
    age: U;
}
const dome: Person<string, number> = {
    name: "sunny",
    age: 18,
};

所以定义泛型接口的时候,正确的写法应该是 对其传入了两个确定的类型。T,U的类型也因此确定了。

泛型接口来约束函数:

interface Person<T> {
    (value: T): Array<T>
}

const printFun: Person<string> = <T>(value: T): Array<T> => {
    let arr: T[] = [];
    arr.push(value)
    return arr;
};
console.log(printFun("233")); //['233']

泛型类

与泛型接口类似,泛型也可以用于类的类型定义中:

class information<T, U>{
    name: T
    age: U
    constructor(name: T, age: U) {
        this.name = name;
        this.age = age
    }
}
let c =  new information<string, number>("张三", 48)

泛型参数的默认类型

在 TypeScript 2.3 以后,我们可以为泛型中的类型参数指定默认类型。当使用泛型时没有在代码中直接指定类型参数,从实际值参数中也无法推测出时,这个默认类型就会起作用。

class information<T = string, U = number>{
    name: T
    age: U
    constructor(name: T, age: U) {
        this.name = name;
        this.age = age
    }
}
let c = new information("李四", 25)

总结:

泛型德优势是什么?

增加类型的复用性和灵活性。

泛型实现的基本方法是什么?

  • 找到不确定类型的部分,为其定义泛型参数
  • 传入参数时,为泛型指定具体的类型

泛型约束的作用是什么?

既可以,保留泛型的灵活性,又限制了一定的规范。


注明:在正式开发中,泛型的使用场景非常多…


🚵‍♂️ 博主座右铭:向阳而生,我还在路上!
——————————————————————————————
🚴博主想说:将持续性为社区输出自己的资源,同时也见证自己的进步!
——————————————————————————————
🤼‍♂️ 如果都看到这了,博主希望留下你的足迹!【📂收藏!👍点赞!✍️评论!】
——————————————————————————————

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C#小轮子:Visual Studio自动编译Sass文件

文章目录 前言插件安装插件使用compilerconfig.jsonsass输入和css输出&#xff08;自动生成&#xff09;默认配置&#xff08;我不懂就不去动他了&#xff09; 前言 我们知道css文件用起来太麻烦&#xff0c;如果样式一多&#xff0c;嵌套起来用css样式就眼花缭乱。Sass使用层…

ElasticSearch:项目实战(1)

es环境搭建参考&#xff1a;ElasticSearch&#xff1a;环境搭建步骤_Success___的博客-CSDN博客 需求&#xff1a; 用户输入关键可搜索文章列表 关键词高亮显示 文章列表展示与home展示一样&#xff0c;当用户点击某一篇文章&#xff0c;可查看文章详情 思路&#xff1a; …

CSS-grid布局

网格布局也叫grid布局&#xff0c;平常写样式的时候基本上都是用的flex布局。 像以下布局&#xff0c;用flex布局就可能会有有点麻烦&#xff0c;这时候用grid布局就方便的多了。 或者是照片墙 grid布局就是将容器划分为行和列&#xff0c;产生单元格&#xff0c;然后在指定的…

ArcGIS Pro技术应用(暨基础入门、制图、空间分析、影像分析、三维建模、空间统计分析与建模、python融合)

GIS是利用电子计算机及其外部设备&#xff0c;采集、存储、分析和描述整个或部分地球表面与空间信息系统。简单地讲&#xff0c;它是在一定的地域内&#xff0c;将地理空间信息和 一些与该地域地理信息相关的属性信息结合起来&#xff0c;达到对地理和属性信息的综合管理。GIS的…

机器学习笔记之优化算法(十一)凸函数铺垫:梯度与方向导数

机器学习笔记之优化算法——凸函数铺垫&#xff1a;梯度与方向导数 引言回顾&#xff1a;偏导数方向余弦方向导数方向导数的几何意义方向导数的定义 方向导数与偏导数之间的关联关系证明过程 梯度 ( Gradient ) (\text{Gradient}) (Gradient) 引言 本节作为介绍凸函数的铺垫&a…

【华秋推荐】新能源汽车中的T-BOX系统,你了解多少?

近几年&#xff0c;新能源汽车产业进入了加速发展的阶段。我国的新能源汽车产业&#xff0c;经过多年的持续努力&#xff0c;技术水平显著提升、产业体系日趋完善、企业竞争力大幅增强&#xff0c;呈现市场规模、发展质量“双提升”的良好局面。同时&#xff0c;通过国家多年来…

IDEA每次启动indexing解决办法

每次启动indexing很浪费时间。 解决办法 setting中搜索index 设置如下&#xff1a; 这样设置以后&#xff0c;启动速度明显快多了。 参考 https://blog.csdn.net/qq_45162113/article/details/121128721

Leetcode24 两两交换链表相邻的节点

迭代解法&#xff1a; class Solution {public ListNode swapPairs(ListNode head) {ListNode dummyHead new ListNode(0);dummyHead.next head;ListNode temp dummyHead;while (temp.next ! null && temp.next.next ! null) {ListNode node1 temp.next;ListNode n…

【单片机】51单片机,晨启科技,板子引脚对应关系

一般引脚: sbit beepP2^4; //将单片机的P2.4端口定义为beep.本口用于屏蔽上电后蜂鸣器响 sbit ledP1^0; //将单片机的P1.0端口定义为led&#xff0c;用于点亮LED-D1 sbit DIG1P0^0; //数码管位选1 sbit DIG2P0^1; //数码管位选2P10xFF;//初始化P1引脚全部置高&a…

树莓派安装Ubuntu系统(无屏幕)

树莓派安装ubuntu系统 前言 软件需要: 1.方案一 win32diskimager-1.0.0-install.exe SDFormatterha Ubuntu镜像&#xff08;可以官网下载也可以清华源&#xff09; 方案二: 树莓派镜像烧录器 树莓派镜像烧录器直达下载 硬件需要: 64GB内存卡&#xff08;推荐Sanddisk Ultra&am…

Java并发编程第4讲——Java中的锁(知识扫盲)

目录 一、锁的相关概念 1.1 什么是锁 1.2 为什么需要锁 1.3 Java中锁的分类 二、synchronized关键字 2.1 三个特点 2.2 三种表现形式&#xff08;&#x1f64b;‍♂️&#xff09; 2.3 sychronized是怎么实现的&#xff08;&#x1f64b;‍♂️&#xff09; 2.4 JDK1.…

用MariaDB创建数据库,SQL练习,MarialDB安装和使用

前言&#xff1a;MariaDB数据库管理系统是MySQL的一个分支&#xff0c;主要由开源社区在维护&#xff0c;采用GPL授权许可 MariaDB的目的是完全兼容MySQL&#xff0c;包括API和命令行&#xff0c;使之能轻松成为MySQL的代替品。在存储引擎方面&#xff0c;使用XtraDB来代替MySQ…

有血有肉的PPT

1、PPT是Powerpoint缩写 2、引申的含义是Powerpoint Power(力量/能量&#xff09; Point(观点/要点) 3、用PPT做的文档是讲演稿&#xff0c;讲演的内容要有力度&#xff0c;之所以要去演讲是为了能够影响受众 4、其次演讲稿上的内容要列出要点、表明观点&#xff0c;所以一般P…

Jmeter入门之digest函数 jmeter字符串连接与登录串加密应用

登录请求中加密串是由多个子串连接&#xff0c;再加密之后传输。 参数连接&#xff1a;${var1}${var2}${var3} 加密函数&#xff1a;__digest &#xff08;函数助手里如果没有该函数&#xff0c;请下载最新版本的jmeter5.0&#xff09; 函数助手&#xff1a;Options > …

2.CUDA 编程手册中文版---编程模型

2.编程模型 更多精彩内容&#xff0c;请扫描下方二维码或者访问https://developer.nvidia.com/zh-cn/developer-program 来加入NVIDIA开发者计划 本章通过概述CUDA编程模型是如何在c中公开的&#xff0c;来介绍CUDA的主要概念。 编程接口中给出了对 CUDA C 的广泛描述。 本章…

在Ubuntu中使用Docker启动MySQL8的天坑

写在前面 简介&#xff1a; lower_case_table_names 是mysql设置大小写是否敏感的一个参数。 1.参数说明&#xff1a; lower_case_table_names0 表名存储为给定的大小和比较是区分大小写的 lower_case_table_names 1 表名存储在磁盘是小写的&#xff0c;但是比较的时候是不区…

微服务Eureka注册中心

目录 一、Eureka的结构和作用 二、搭建eureka-server 三、服务注册 四、服务发现 假如我们的服务提供者user-service部署了多个实例&#xff0c;如图&#xff1a; 存在的问题&#xff1a; order-service在发起远程调用的时候&#xff0c;该如何得知user-service实例的ip地址…

使用自己的数据集预加载 Elasticsearch

作者&#xff1a;David Pilato 我最近在讨论论坛上收到一个问题&#xff0c;关于如何修改官方 Docker 镜像以提供一个现成的 Elasticsearch 集群&#xff0c;其中已经包含一些数据。 说实话&#xff0c;我不喜欢这个想法&#xff0c;因为你必须通过提 entrypoint.sh 的分叉版本…

管理类联考——逻辑——论证逻辑——汇总篇——真题和典例——解释

解释 1. 解释现象 199-2016-1-42——解释现象——并列现象——在二者之间建立联系 某公司办公室茶水间提供自助式收费饮料。职员拿完饮料后&#xff0c;自己把钱放到特设的收款箱中。研究者为了判断职员在无人监督时&#xff0c;其自律水平会受哪些因素的影响&#xff0c;特…

vscode的ros拓展(插件)无法渲染urdf

文章目录 事件背景资料调查解决方案 事件背景 之前在vscode中一直用得好好的urdf预览功能&#xff0c;突然在某一天&#xff0c;不行了。 执行 URDF Preview之后&#xff0c;虽然弹出了一个URDF Preview的窗口&#xff0c;但是这个窗口里面啥都没有。没有网格、没有模型。 一开…