typescript学习回顾(五)

news2024/11/17 9:19:47

今天来分享一下ts的泛型,最后来做一个练习

泛型

有时候,我们在书写某些函数的时候,会丢失一些类型信息,比如我下面有一个例子,我想提取一个数组的某个索引之前的所有数据

function getArraySomeData(newArr, n:number) {
    let newArr2:any[] = [];
    newArr.forEach((it, i) => {
        if (n > i) {
            newArr2.push(it);
        }
    });

    return newArr2;
}

const arr = getArraySomeData(['1112', '1213', '121'], 2);
console.log(arr)

但是这个数组它可以是任意类型的,可以是对象,字符串,数字数组,这个时候不约束的话会存在ts的隐患,这个时候就有了泛型的概念。

概念

泛型的一个概念:

泛型相当于是一个类型变量,在定义时,无法预先知道具体的类型,可以用该变量来代替,只有在调用时,才能确定它的类型

很多时候,TS会智能的根据传递的参数,推导出泛型的具体类型

我们可以把刚才的代码使用泛型改成这种形式

function getArraySomeData<T>(newArr:T[], n:number) {
    let newArr2:T[] = [];
    newArr.forEach((it, i) => {
        if (n > i) {
            newArr2.push(it);
        }
    });

    return newArr2;
}

const arr = getArraySomeData(['1112', '1213', '121'], 2);
console.log(arr)

如果没有传递具体类型,无法完成推导,默认是空对象。

进行传值

如果我 传递值只有ts会根据传递的类型进行严格类型检查,如下图,传递的是number,传递的就必须都是number

在这里插入图片描述

泛型设置默认值
function getArraySomeData<T = number>(newArr:any[], n:number) {

}
在类型别名、接口、类使用泛型

回调函数,判断数组的某一项是否满足条件,这个某一项可以用泛型来代替

类型别名

type callback<T> = (n:T,i:number) => boolean;

接口

下面手动写了一个筛选的filter函数

interface callback<T> = (n:T,i:number) => boolean;

function filter<T>(arr: T[], callback: callback<T>): T[] {
    const newArr: T[] = [];

    arr.forEach((n, i) => {
        if (callback(n, i)) {
            newArr.push(n);
        }
    });
    return newArr;
}

下面这个例子是一个数组帮助类,通过在类最外面设置了泛型T,来约束里面所有的方法的泛型,之后传递的所有的参数泛型以及数组放行,都是传递的值。

export class ArrayHelper<T> {
    constructor(private arr:T[]){

    }

    take(n: number): T[] {
        if (n >= this.arr.length) {
            return this.arr;
        }
        const newArr: T[] = [];
        for (let i = 0; i < n; i++) {
            newArr.push(this.arr[i])
        }
        return newArr;
    }

    shuffle() {
        for (let i = 0; i < this.arr.length; i++) {
            const targetIndex = this.getRandom(0, this.arr.length);
            const temp = this.arr[i];
            this.arr[i] = this.arr[targetIndex];
            this.arr[targetIndex] = temp;
        }
    }

    private getRandom(min: number, max: number) {
        const dec = max - min;
        return Math.floor(Math.random() * dec + min)
    }
}
泛型约束

这个是在有些特定场景的时候会需要使用,这里举一个简单的例子,我传递一个对象,然后我需要把这个对象的时间戳转换成日期字符串的形式

function dateFormat<T>(obj:T):T{
	obj.time = util.timeFormat(obj.time);
	return obj;
}

这个时候,ts会智能报错,报错的位置是obj.time的位置,因为泛型可以传递的类型是任意的类型,所以我用对象属性的方式,ts会进行报错,所以这种情况需要类型的约束

具体怎么做呢,很简单

interface hasTimePro{
	time : number
}

function dateFormat<T extends hasTimePro>(obj:T):T{
	obj.time = util.timeFormat(obj.time);
	return obj;
}

上面通过接口定义要约束的泛型的类型,可以是对象,也可以是其他。然后在泛型里进行继承,继承这个接口,这样就可以对这个泛型进行一个约束。

多泛型

在很多情况下,我们可能参数特别多,要限制的类和接口可能不止一个,所以ts同样支持可以有多个泛型,具体的使用例子

我希望混合两个 数组,数组1和数组2,两个可能都是不一样的数组,但是两个数组长度必须一样,至于传递什么类型不管,只负责混合。这里就可以通过英文逗号将泛型隔开,然后设置多个泛型

function mixinArray<T, K>(arr1: T[], arr2: K[]): (T | K)[] {
    if (arr1.length !== arr2.length) {
        throw new Error('两个数组长度不等');
    }
    let result: (T | K)[] = [];
    for (let i = 0; i < arr1.length; i++) {
        result.push(arr1[i]);
        result.push(arr2[i]);
    }

    return result;
}

const result = mixinArray([1, 3, 4], ["a", "b", "c"]);

result.forEach(r => console.log(r));
小练习
开发一个字典类(Dictionary),字典里会保存键值对的数据

键值对数据的特点:
- 键(key)可以是任何类型,但不允许重复
- 值(value)可以是任何类型
- 每一个键对应一个值
- 所有的键类型相同,所有的值类型相同

字典类对键值对数组的操作:

- 添加一个键值对
- 按照键删除对应的键值对
- 循环每一个键值对
- 得到当前键值对的数量
- 判断某个键是否存在
- 重新设置某个键的值,如果不存在,就添加
代码
  • src

    • dictionary.ts
    export type CallBack<K, V> = (key: K, val: V) => void
    
    export class Dictonary<K, V> {
        private keys: K[] = [];
        private vals: V[] = [];
    
    
        get size() {
            return this.keys.length;
        }
    
        set(key: K, val: V) {
            const i = this.keys.indexOf(key)
            if (i < 0) {
                this.keys.push(key);
                this.vals.push(val);
            } else {
                this.vals[i] = val;
            }
        }
    
        forEach(callback: CallBack<K, V>) {
            this.keys.forEach((k, i) => {
                const v = this.vals[i];
                callback(k, v);
            });
        }
    
        has(key: K) {
            return this.keys.includes(key);
        }
    
        delete(key: K) {
            const i = this.keys.indexOf(key);
            if (i === -1) {
                return;
            }
            this.keys.splice(i, 1);
            this.vals.splice(i, 1);
        }
    }
    
    • index.ts
    import { Dictonary } from "./dictionary";
    
    const dic = new Dictonary<string, number>();
    
    dic.set('a', 1);
    dic.set('b', 1);
    dic.set('a', 12);
    dic.set('c', 1231);
    
    dic.forEach((d,i)=>{
        console.log(`key:${d},v:${i}`)
    });
    
    dic.delete('b');
    
    dic.forEach((d,i)=>{
        console.log(`key:${d},v:${i}`)
    });
    
    console.log('当前键值对的数量:' + dic.size)
    

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

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

相关文章

AI系统:未来科技的驱动力

引言 人工智能&#xff08;Artificial Intelligence, AI&#xff09;是一门研究如何使计算机模拟、延伸和扩展人类智能的学科。自20世纪50年代起&#xff0c;人工智能作为一项科学研究领域开始兴起。早期的AI系统主要集中在简单的任务&#xff0c;如棋类游戏和数学证明。随着计…

NLP篇1

场景&#xff1a;假设给你一篇文章。 目标&#xff1a;说白了&#xff0c;就是数学的分类。但是如何实现分类呢。下面将逐步一 一 分析与拆解。先把目标定好了和整体框架定好了。而不是只见树木而不见森林。 情感分类&#xff08;好评、差评&#xff0c;中性&#xff09; 整体…

Windows 安装 Terraform

Windows 安装 Terraform 下载 Terraform 压缩文件安装 Terraform测试 Terraform 下载 Terraform 压缩文件 访问 https://developer.hashicorp.com/terraform/install&#xff0c;下载 Windows 版安装文件&#xff0c; 安装 Terraform 解压下载 zip 包&#xff0c;然后将解压的…

使用gitlab的CI/CD实现logseq笔记自动发布为单页应用

使用gitlab的CI/CD实现logseq笔记自动发布为单页应用 使用gitlab的CI/CD实现logseq笔记自动发布为单页应用如何实现将logseq的笔记发布成网站使用 logseq-publish-docker 实现手动发布使用gitlab的CI/CD实现自动发布过程中的问题及解决参考资料 使用gitlab的CI/CD实现logseq笔记…

2.IOC

IOC介绍 控制反转&#xff0c;把对象的创建和调用的过程&#xff0c;交给spring进行管理。 使用IOC目的&#xff1a;为了耦合度降低。 IOC底层原理 1&#xff09;xml解析 2&#xff09;工厂模式 3&#xff09;反射 IOC思想基于IOC容器完成&#xff0c;IOC容器底层就是对…

QT的编译过程

qmake -project 用于从源代码生成项目文件&#xff0c;qmake 用于从项目文件生成 Makefile&#xff0c;而 make 用于根据 Makefile 构建项目。 详细解释&#xff1a; qmake -project 这个命令用于从源代码目录生成一个初始的 Qt 项目文件&#xff08;.pro 文件&#xff09;。它…

使用deep修改前端框架中的样式

目录 1.deep的作用 2.使用方式 3.特别说明 scoped 的实现原理&#xff1a; !important 1.deep的作用 /deep/、::v-deep 和 :deep 都是用于穿透组件作用域的选择器。它们的主要目的是允许开发者在父组件中直接选择并样式化子组件内部的元素&#xff0c;即使这些元素被封装在…

工业除尘自动化中的Profibus转Modbus网关应用解析

一、背景 在工业生产过程中&#xff0c;除尘系统扮演着至关重要的角色&#xff0c;它不仅可以保护生产设备&#xff0c;延长设备寿命&#xff0c;还可以减少环境污染&#xff0c;提高生产效率。而Profibus转Modbus网关&#xff08;XD-MDPB100&#xff09;作为自动化领域中的关…

通俗易懂的chatgpg的原理简介

目录 一、深度学习与语言模型 二、ChatGPT训练三步走 三、情景学习与思维链 四、修改提示语优化结果 五、能力评估和注意问题 六.算法原理 简介&#xff1a; ChatGPT的人工智能原理主要基于深度学习技术&#xff0c;特别是大规模的预训练语言模型和Transformer结构。Cha…

YOLOv8的5种不同部署方式推理速度对比:Pytorch、ONNX、OpenVINO-FP32、OpenVINO-int8、TensorRT

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

隐私计算实训营第二期第十课:基于SPU机器学习建模实践

隐私计算实训营第二期-第十课 第十课&#xff1a;基于SPU机器学习建模实践1 隐私保护机器学习背景1.1 机器学习中隐私保护的需求1.2 PPML提供的技术解决方案 2 SPU架构2.1 SPU前端2.2 SPU编译器2.3 SPU运行时2.4 SPU目标 3 密态训练与推理3.1 四个基本问题3.2 解决数据来源问题…

数据结构(Java):迭代器遍历【底层源码解析】

1、引言 我们知道&#xff0c;对于List系列集合&#xff0c;添加的元素是有序、可重复、有索引的&#xff1b;而对于Set系列集合&#xff0c;添加的元素是无序、不重复、无索引的。 那么使用for循环通过下标来对Set系列集合进行遍历&#xff0c;那显然是不行的。 迭代器就可…

RabbitMQ 之 延迟队列

目录 ​编辑一、延迟队列概念 二、延迟队列使用场景 三、整合 SpringBoot 1、创建项目 2、添加依赖 3、修改配置文件 4、添加 Swagger 配置类 四、队列 TTL 1、代码架构图 2、配置文件代码类 3、生产者 4、消费者 5、结果展示 五、延时队列优化 1、代码架构图 …

鸿蒙生态应用开发白皮书V3.0

来源&#xff1a;华为&#xff1a; 近期历史回顾&#xff1a;

yolov8对新的数据集自动标注

项目地址 https://github.com/ultralytics/ultralytics 极简运行效果 获取模型bbox的极简demo 有时候是想要获取yolo检测的bbox框。 import random import cv2 as cv from ultralytics import YOLO# model YOLO("yolov8m.yaml") # model YOLO("yolov8m.pt…

【FPGA】Verilog:全减器与半减器 | Full Subtractor | Half Subtractor

0x00 全减器(Full Subtractor) 减法器是用于减法运算的逻辑电路,与不包含借位的半减法器不同。 全减法器因为包含借位的产生与否,所以具备完整的减法功能。 输出由差 和借位 组成:

开源模型应用落地-FastAPI-助力模型交互-WebSocket篇(五)

一、前言 使用 FastAPI 可以帮助我们更简单高效地部署 AI 交互业务。FastAPI 提供了快速构建 API 的能力,开发者可以轻松地定义模型需要的输入和输出格式,并编写好相应的业务逻辑。 FastAPI 的异步高性能架构,可以有效支持大量并发的预测请求,为用户提供流畅的交互体验。此外,F…

物联网工业级网关解决方案 工业4G路由器助力智慧生活

随着科技的飞速发展&#xff0c;无线通信技术正逐步改变我们的工作与生活。在这个智能互联的时代&#xff0c;一款高性能、稳定可靠的工业4G路由器成为了众多行业不可或缺的装备。工业4G路由器以其卓越的性能和多样化的功能&#xff0c;助力我们步入智慧新纪元。 一、快速转化&…

SpringBoot+ELK 收集日志的两种方式

方式一、FileBeatlogstash 7.5.1(docker)ES(docker)springboot 日志文件 应用方式 我们采用ELFK 架构采集日志&#xff0c;直接读取日志生成的文件&#xff0c;不对Springboot的日志任何的修改。也就是FileBeat 通过读取日志文件位置获取日志内容&#xff0c;然后发送至logsta…

综合项目实战--jenkins流水线

一、流水线定义 软件生产环节,如:需求调研、需求设计、概要设计、详细设计、编码、单元测试、集成测试、系统测试、用户验收测试、交付等,这些流程就组成一条完整的流水线。脚本式流水线(pipeline)的出现代表企业人员可以更自由的通过代码来实现不同的工作流程。 二、pi…