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);

以上。

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

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

相关文章

药品商品名/通用名/化学名/别名-数据库查询方法

药品通用名-药品化学名-药品商品名的区别 药品通用名通常是由药典委员会或相关药品命名机构根据药品的化学成分或治疗特性制定的标准化名称。这个名称在科学和医疗领域中用于确保对药品的准确和一致性识别。如阿司匹林&#xff08;Aspirin&#xff09;是药品的通用名。&#x…

Tomact安装配置及使用(超详细)

文章目录 web相关知识概述web简介(了解)软件架构模式(掌握)BS&#xff1a;browser server 浏览器服务器CS&#xff1a;client server 客户端服务器 B/S和C/S通信模式特点(重要)web资源(理解)资源分类 URL请求路径(理解)作用介绍格式浏览器通过url访问服务器的过程 服务器(掌握)…

Vue.js课后练习(登录注册和大小比较)

第一题 请编写登录页面和注册页面&#xff0c;通过动态组件实现动态切换页面中显示的组件&#xff0c;效果如图1和图2所示。 图1 登录页面 图2 注册页面 代码&#xff1a; my.vue代码: <template>登录 </template><script setup> </script><st…

maven聚合,继承等方式

需要install安装到本地仓库&#xff0c;或者私服&#xff0c;方可使用自己封装项目 编译&#xff0c;测试&#xff0c;打包&#xff0c;安装&#xff0c;发布 parent: <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://mav…

PotatoPie 4.0 实验教程(33) —— FPGA实现摄像头视频图像叠加

链接直达 https://item.taobao.com/item.htm?ftt&id776516984361 什么是视频水印&#xff1f; 视频水印就是图像叠加&#xff0c;跟画中画&#xff0c;或者是OSD是一样的原理&#xff0c;都是在视频的行场数据流上进行替换操作&#xff0c;比如叠加可以直接用水印图的数…

力扣刷题 63.不同路径 II

题干 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish”&#xff09;。 现在考虑网格中有障碍物。那么从左上角到…

LLM大语言模型(十三):ChatGLM3-6B兼容Langchain的Function Call的一步一步的详细转换过程记录

# LangChain&#xff1a;原始prompt System: Respond to the human as helpfully and accurately as possible. You have access to the following tools: Calculator: Useful for when you need to calculate math problems, args: {\calculation\: {\description\: \calcul…

学习VUE2第6天

一.请求拦截器 可以节流&#xff0c;防止多次点击请求 toast是单例 二.前置路由守卫 在Vue.js中&#xff0c;前置路由守卫是指在路由转换实际发生之前执行的钩子函数。这是Vue Router&#xff08;Vue.js官方的路由管理器&#xff09;提供的一种功能&#xff0c;允许开发者在用…

Oracle 终于在 MySQL 8.4 对 InnoDB 默认值下手了

根据 Oracle 的官方文档&#xff0c;MySQL 8.4 相比于 8.0 调整了不少 InnoDB 的默认值。 新的改动使得默认值更加接近于当前的硬件水平。比如 innodb_io_capacity&#xff0c;之前 200 对应的是机械盘。10000 更加符合主流 SSD 的指标。 之前 MySQL 里 InnoDB 的默认值已经过时…

go代码运行报错go_test3\main.go:14:2: package test3/mymath is not in std

在使用vscode运行go代码时报错 go_test3\main.go:14:2: package test3/mymath is not in std 如下图 产生的原因&#xff1a;使用右键Run Code&#xff0c;或者点击vscode运行按钮也会报错&#xff0c;如下图&#xff1a; 解决办法&#xff1a; 在终端执行go run main.go运…

爬虫学习:基本网络请求库的使用

目录 一、urllib网络库 1.urlopen()方法 2.request方法 二、requests网络请求库 1.主要方法 2.requests.get()和requests.post() 一、urllib网络库 1.urlopen()方法 语法格式&#xff1a; urlopen(url,data,timeout,cafile,capath,context) # url:地址 # data:要提交的数据…

关于Dockerfile镜像实例

文章目录 Dockerfile镜像实例一、构建SSH镜像1、建立工作目录2、生成镜像3、启动容器并修改root密码 二、构建systemd镜像1、建立工作目录2、生成镜像3、运行镜像容器4、测试容器systemd 三、构建Nginx镜像1、建立工作目录2、编写Dockerfile脚本3、编写run.sh启动脚本4、生成镜…