TS学习-泛型基础

目录

  • 1,介绍
    • 1,在函数中使用
    • 2,在类型别名,接口中使用
    • 3,在类中使用
  • 2,泛型约束
  • 3,多泛型
  • 4,举例实现 Map

1,介绍

泛型相当于是一个类型变量,有时无法预先知道具体的类型,可以用泛型来代替。

通常会附属于函数,类,接口,类型别名之上。

举例:

在定义函数时,有时会丢失一些类型信息(多个位置应该保持一致)。

function handleArray(arr: any[], n: number): any[] {
    const temp: any[] = arr.slice(n)
    return temp
}

handleArray([1,2,30], 2)
handleArray(['1', '2', '3'], 2)

当传递 number 类型数组时,上面代码中所有 any[] 都应该是 number[],string 数组同理。

泛型来解决:

function handleArray<T>(arr: T[], n: number): T[] {
    const temp: T[] = arr.slice(n)
    return temp
}

handleArray<number>([1,2,30], 2)
handleArray<string>(['1', '2', '3'], 2)

1,在函数中使用

使用方式:定义函数和调用函数时,都在函数名之后使用 < > 来定义泛型名称

function handleArray<T>(arr: T[]): T[] {
   // ...
}

handleArray<number>()
handleArray<string>()

泛型对函数来说:在调用函数时,告诉函数操作的具体类型,函数在执行时就能确定具体的类型。

特点

1,只有在调用时,才能确定泛型的具体类型。

2,一般情况下,TS会智能的根据传递的参数,推导出泛型的具体类型。

以上面的例子来说,即便调用时没有写具体的泛型类型,函数也会根据传递的参数智能推导:

在这里插入图片描述

如果无法完成推导,并且没有传递具体的类型,默认为 unknown

function handleArray<T>(arr: any[], n: number): T[] {
    const temp: T[] = arr.slice(n)
    return temp
}

// unknown[]
const res = handleArray([1,2,30], 2)

3,泛型也可以有默认值。

几乎用不到,因为泛型就是用来表示可能得任意类型。

function handleArray<T = number>(arr: T[]): T[] {
    // ...
}

2,在类型别名,接口中使用

看例子即可,实现一个 filter 函数。

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

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

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

function filter<T>(arr: T[], callback: callback<T>): T[] {
    let temp: T[] = [];
    arr.forEach((n, i) => {
        if (callback(n, i)) {
            temp.push(arr[i]);
        }
    });
    return temp;
}

const res = filter([1, 2, 3, 4], (n, i) => n % 2 !== 0);
console.log(res);

3,在类中使用

类名上指定的泛型,可以传递到定义的属性和方法上。

type callback<T> = (item: T, index?: number, arr?: T[]) => boolean;

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

	myFilter(callback: callback<T>): T[] {
		let tempArr: T[] = [];
		this.arr.forEach((item, index, arr) => {
			if (callback(item, index, arr)) {
				tempArr.push(item);
			}
		});
		return tempArr;
	}
}

const tempArr = new ArrayHelper([2, 3, 4, 5]);

const res = tempArr.myFilter((item) => item % 2 === 0);

console.log(res);

2,泛型约束

用于约束泛型的取值:必须得有类型约束(接口,类型别名)中的成员。

举例:泛型必须兼容 User 接口。

interface User {
    name: string;
}

function updateName<T extends User>(obj: T): T {
    obj.name = obj.name.toUpperCase();
    return obj;
}

const obj = {
    name: "lover",
    age: 19,
};

const newNameObj = updateName(obj);
console.log(newNameObj);

3,多泛型

函数的参数会有多个,所以泛型也会有多个。

举例,混合2个不同类型的数组。

function mixinArray<T, K>(arr1: T[], arr2: K[]): (T | K)[] {
    const temp: (T | K)[] = [];
    for (let i = 0; i < arr1.length; i++) {
        temp.push(arr1[i]);
        temp.push(arr2[i]);
    }
    return temp;
}

console.log(mixinArray([1, 2], ["11", "22"]));

4,举例实现 Map

这是 Map 的接口定义

interface Map<K, V> {
    clear(): void;
    /**
     * @returns true if an element in the Map existed and has been removed, or false if the element does not exist.
     */
    delete(key: K): boolean;
    /**
     * Executes a provided function once per each key/value pair in the Map, in insertion order.
     */
    forEach(callbackfn: (value: V, key: K, map: Map<K, V>) => void, thisArg?: any): void;
    /**
     * Returns a specified element from the Map object. If the value that is associated to the provided key is an object, then you will get a reference to that object and any change made to that object will effectively modify it inside the Map.
     * @returns Returns the element associated with the specified key. If no element is associated with the specified key, undefined is returned.
     */
    get(key: K): V | undefined;
    /**
     * @returns boolean indicating whether an element with the specified key exists or not.
     */
    has(key: K): boolean;
    /**
     * Adds a new element with a specified key and value to the Map. If an element with the same key already exists, the element will be updated.
     */
    set(key: K, value: V): this;
    /**
     * @returns the number of elements in the Map.
     */
    readonly size: number;
}

简单模拟实现:

class MyMap<K, V> {
    private keys: K[] = [];
    private values: V[] = [];

    get size() {
        return this.keys.length;
    }

    clear(): void {
        this.keys = [];
        this.values = [];
    }

    delete(key: K): boolean {
        const index = this.keys.indexOf(key);
        if (index !== -1) {
            this.keys.splice(index, 1);
            this.values.splice(index, 1);
            return true;
        } else {
            return false;
        }
    }

    forEach(callbackfn: (value: V, key: K, map: MyMap<K, V>) => void): void {
        this.keys.forEach((item, i) => {
            callbackfn(this.values[i], item, this);
        });
    }

    get(key: K): V | undefined {
        const index = this.keys.indexOf(key);
        return this.values[index];
    }

    has(key: K): boolean {
        return return this.keys.includes(key);
    }

    set(key: K, value: V): this {
        const index = this.keys.indexOf(key);
        if (index !== -1) {
            this.keys.push(key);
            this.values.push(value);
        } else {
            this.values[index] = value;
        }
        return this;
    }
}

const myMap = new MyMap<string, number>();

myMap.set("a", 1);
myMap.set("b", 2);
myMap.set("c", 3);
console.log(myMap.get("d"));
myMap.has("a");
console.log(myMap.delete("c"));

myMap.forEach((value, key, self) => {
    console.log(value, key, self);
});

myMap.clear();
console.log(myMap.size);

以上。

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

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

相关文章

JavaWeb--1.Servlet

Servlet&#xff08;基础&#xff09; 1、配置依赖&#xff1a; ​ 在pom.xml文件中加入相关依赖 <dependencies><dependency><groupId>jakarta.servlet</groupId><artifactId>jakarta.servlet-api</artifactId><version>5.0.0&l…

数据结构--栈与队列【您的关注是我创作的动力!】

文章目录 栈什么是栈&#xff1f;栈的具体实现 队列什么是队列&#xff1f;队列的实现 栈 什么是栈&#xff1f; 栈也是顺序表的一种&#xff0c;栈的逻辑实现是先进后出&#xff08;后进先出&#xff09;就跟子弹夹一样。 具体逻辑就是它只允许在固定的一端进行数据的插入与…

eNSP-抓包解析HTTP、FTP、DNS协议

一、环境搭建 1.http服务器搭建 2.FTP服务器搭建 3.DNS服务器搭建 二、抓包 三、http协议 1.HTTP协议&#xff0c;建立在FTP协议之上 2.http请求 3.http响应 请求响应报文参考&#xff1a;https://it-chengzi.blog.csdn.net/article/details/113809803 4.浏览器开发者工具抓包…

C++ 函数 参数与返回值

#一 参数与返回值 回顾文件读数据功能 文件读数据 1函数参数传值调用过程 将函数调用语句中的实参的一份副本传给函数的型材。 简单的值的传递&#xff0c;实参的值没有发生变化。 2 函数参数传值调用过程 传地址调用 将变量的地址传递给函数的形参 形参和实参指向了同…

webpack与vite

webpack 使用步骤&#xff1a; 初始化项目 pnpm init -y安装依赖webpack、webpack-cli在项目中创建src目录&#xff0c;然后编写代码&#xff08;index.js&#xff09;执行pnpm weboack来对代码进行打包&#xff08;打包后观察dist文件夹&#xff09; 配置古文件&#xff08;w…

数智新重庆 | 推进信号升格 打造算力山城

2024年&#xff0c;是实现“十四五”规划目标任务的关键一年&#xff0c;高质量的5G网络、强大的AI能力作为新质生产力的重要组成部分&#xff0c;将有效赋能包括制造业在内的千行万业数字化化、智能化、绿色化转型升级&#xff0c;推动融合应用新业态、新模式蓬勃兴起&#xf…

字符函数与字符串函数(2)

遇见她如春水映莲花 字符函数与字符串函数&#xff08;2&#xff09; 前言一、strcatstrncat 二、strcmpstrncmp在这里插入图片描述 三、strstr四、strtok五、strerror总结 前言 根据上期字符函数与字符串函数我们可以了解到字符函数与个别字符串函数的用法&#xff0c; 那么接…

SQL注入less-1

一、启动SQL注入的靶场 1、启动phpstudy 注&#xff1a;phpstudy默认的php版本为7.x&#xff0c;想要成功的搭建靶场&#xff0c;需要把php版本改为5.x 2、输入127地址加文件名 进入此界面后点击setup就行 3、进入less-1的关卡 靶场搭建成功 二、查看less-1的代码 注&#…

什么?300TB SSD要来了?

SK海力士在韩国首尔的一场新闻发布会上宣布&#xff0c;其正在研发一款前所未有的300TB容量的固态硬盘&#xff08;SSD&#xff09;。这款硬盘的预告是该公司一系列旨在推动数据中心和设备端AI能力发展的产品与技术组合的一部分。SK海力士引用市场研究预测&#xff0c;全球在AI…

每日一题(力扣740):删除并获得点数--dp+思维

其实跟打家劫舍没啥区别 排序去重之后去考虑当前位置和前两个位置之间的关系即可&#xff0c;具体见代码&#xff1a; class Solution { public:int deleteAndEarn(vector<int>& nums) {int n nums.size();if (n 1) return nums[0];unordered_map<int, int>…

代码随想录算法训练营DAY51|C++动态规划Part12|1143.最长公共子序列、1035.不相交的线、53.最大子序列和

文章目录 1143.最长公共子序列思路CPP代码 1035.不相交的线53.最大子序列和思路CPP代码 1143.最长公共子序列 力扣题目链接 文章讲解&#xff1a;1143.最长公共子序列 视频讲解&#xff1a;动态规划子序列问题经典题目 | LeetCode&#xff1a;1143.最长公共子序列 本题其实就跟…

GPU虚拟化和算力隔离探讨

1. 术语介绍 术语 全称 说明 GPU Graphics Processing Unit 显卡 CUDA Compute Unified Device Architecture 英伟达2006年推出的计算API VT/VT-x/VT-d Intel Virtualization Technology -x表示x86 CPU&#xff0c;-d表示Device SVM AMD Secure Virtual Machine …

ASP.NET视频点播系统的设计与实现

摘 要 本文阐述了基于WEB的交互式视频点播系统的协议原理、软件结构和设计实现。本视频点播系统根据流媒体传输原理&#xff0c;在校园局域网的基础上模拟基于Web的视频点播系统&#xff0c;实现用户信息管理、视频文件的添加、删除、修改及在线播放和搜索功能。本系统是一个…

6.块元素和行内元素

块元素 无论内容多少&#xff0c;该元素独占一行(p、 h1-h6…) 例子如下图 行内元素 内容撑开宽度&#xff0c;左右都是行内元素的可以排在一排(a、 strong、 em …) 例子如下 感谢您的观看&#xff0c;能和您一起学习是我最大的荣幸&#xff01; 文章学习资料&#xff1a;…

【快速入门Linux】10_Linux命令—Vi编辑器

文章目录 一、vi 简介1.1 vi1.2 vim1.3查询软连接命令&#xff08;知道&#xff09; 二、打开和新建文件&#xff08;重点&#xff09;2.1 打开文件并且定位行2.2 异常处理 三、vi三种工作模式&#xff08;重点&#xff09;3.1 末行模式-命令 四、常用命令4.0 命令线路图4.1 移…

url对象---了解url的结构

什么是url url是网页网页的地址&#xff0c;通过一个url我们可以访问到网页&#xff0c;同时url也可以用来引用文件(txt,json,jpg,js,css,html)&#xff0c;所以你可以理解成url是一个指示器&#xff0c;它可以指向一个文件&#xff0c;网页&#xff0c;图片&#xff0c;或者音…

《网络安全技术 网络安全众测服务要求》

近日&#xff0c;全国网络安全标准化技术委员会发布《网络安全技术 网络安全众测服务要求》&#xff08;GB/T 43741-2024&#xff0c;以下简称“众测服务要求”&#xff09;&#xff0c;并将在2024年11月1日正式实施。 《众测服务要求》确立了网络安全众测服务的角色及其职责&…

【skill】移动云服务器80端口

上个月玩CentOS7&#xff0c;提到alist端口问题&#xff0c;https://www.bilibili.com/read/cv33662501/ 云服务器不能被外网访问的原因 1 云服务器没放行端口 2 防火墙没放行端口 3 配置了端口转发 4 浏览器不支持搭建的网页 5 端口被其他软件占用 移动10086云服务的80端口…

ubuntu ros noetic 编译 ORB_SLAM2 过程记录

1. 连接 eigen库 sudo ln -s /usr/include/eigen3/Eigen /usr/include/Eigen 2. opencvx 修改 CMakeList.txt 中的 find_package open cv版本 修改 include/orbExtracter.h 文件为&#xff1a; //#include <opencv2/opencv.hpp> #include<opencv2/imgproc/imgpro…

用魔法打败魔法:用360解除chrome浏览器的360主页

面临的问题&#xff1a; 试了108种方法都是不好使的。 后来看到&#xff1a; https://blog.csdn.net/qq_30267617/article/details/120373704 的介绍&#xff0c;发现可以呀。 三个步骤 步骤1 单击“功能大全” 步骤2 单击“主页防护” 步骤3 在这里更改。