TypeScript 学习笔记 — 泛型的使用(七)
泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。
泛型可以用于 函数 对象 类...
一.指定函数参数类型
单个泛型
案例:创建一个指定长度的数组,同时将每一项都填充一个默认值,根据参数不同,处理结果不同,入参和返回值有映射关系
// 这样写 此时入参和返回值类型就固定了,无法再进行扩展,想需要复用时就不方便
const getArray = (times: number, val: string): string[] => {
let res = [];
for (let i = 0; i < times; i++) {
res.push(val);
}
return res;
};
getArray(3, "a");
getArray(3, 1); // 当val改为 其他类型时,就会报错,类型不匹配,无法复用
使用泛型改写后得代码:会根据传入的类型进行推导
const getArray = <T>(times: number, val: T): T[] => {
let res = [];
for (let i = 0; i < times; i++) {
res.push(val);
}
return res;
};
getArray(3, "a"); // const getArray: <string>(times: number, val: string) => string[]
getArray(3, 1); // const getArray: <number>(times: number, val: number) => number[]
getArray(3, true); //const getArray: <boolean>(times: number, val: boolean) => boolean[]
多个泛型
定义泛型的时候,可以一次定义多个类型参数:案例:元组交换
function swap(tuple: [number, string]): [string, number] {
return [tuple[1], tuple[0]];
}
swap([7, "seven"]);
swap([7, 8]); // 当改为 其他类型时,就会报错,类型不匹配,无法复用
使用泛型改写后得代码:
function swap<T, U>(tuple: [T, U]): [U, T] {
return [tuple[1], tuple[0]];
}
swap([7, "seven"]);
swap([7, 8]); // 可以正确推导类型
二.函数标注的方式
类型定义比较长时,建议使用interface
或type
关键词单独声明,函数中多用type
类型别名 type
类型别名不能被继承和实现
type ISwap = <T, U>(aaa: [T, U]) => [U, T];
const swap: ISwap = (tuple) => [tuple[1], tuple[0]];
swap([7, "seven"]);
接口 interface
interface ISwap {
<T, U>(tuple: [T, U]): [U, T];
}
const swap: ISwap = (tuple) => [tuple[1], tuple[0]];
swap([7, "seven"]);
*案例分析:
const forEach = <T>(arr: T[], callback: (item: T, idx: number) => void) => {
for (let i = 0; i < arr.length; i++) {
callback(arr[i], i);
}
};
forEach(["a", "b", "c"], function (item, idx) {
console.log(item);
});
进行类型的抽离,先抽离 callback 类型,在抽离函数类型
需要注意的是, 写在等号前和后是有区别的:
<T> 写在等号前:使用接口的时候确定的类型,也就是回调函数并没有真正执行时,就可以知道参数类型
<T> 写在等号后:在调用函数的时候确定了类型
type ICallback<T> = (item: T, idx: number) => void; // 使用接口的时候确定的类型,也就是回调函数并没有真正执行时,就可以知道参数类型
type IForEach = <T>(arr: T[], callback: ICallback<T>) => void; // 在调用函数的时候确定了类型
const forEach: IForEach = (arr, callback) => {
for (let i = 0; i < arr.length; i++) {
callback(arr[i], i);
}
};
forEach(["a", "b", "c"], function (item, idx) {
console.log(item);
});
三.默认泛型
可以为泛型中的类型参数指定默认类型。也就是说给泛型增加了默认值,当使用泛型时没有在代码中直接指定类型参数,从实参中也无法推测出时,默认类型就会起作用。
type Union<T = string> = T | number;
type t1 = Union; // type t1 = string | number
type t2 = Union<boolean>; // type t2 = number | boolean
四.泛型约束
约束传入的泛型类型 A extends B, A 是 B 的子类型
function handle<T extends number | string>(val: T): T {
return val;
}
let r1 = handle(123);
let r2 = handle("abc");
let r3 = handle(true); // 报错
泛型必须包含某些属性,length
interface IWithLength {
length: number;
}
function getLen<T extends IWithLength>(val: T) {
return val.length;
}
getLen((a: number, b: string) => {});
约束索引的签名,返回泛型中指定属性,若访问了泛型中不存在属性,就是报错提示
function getVal<T extends object, U extends keyof T>(obj: T, key: U) {
return obj[key];
}
getVal({ a: 1, b: 2, c: 3 }, "c");
五.泛型接口使用
对象中可以使用泛型 常见的就是描述接口的返回值,将复杂的接口,通过泛型拆分开
interface ApiResponse<T = any> {
code: number;
data: T;
message?: string;
}
interface LoginRes {
token: string;
}
function toLogin(): ApiResponse<LoginRes> {
return {
code: 200,
data: {
token: "Bearer token",
},
};
}
let r = toLogin();
r.data.token;
六.类中的泛型
创建实例时提供类型进行泛型约束
class MyList<T extends number | string> {
private arr: T[] = [];
add(val: T) {
this.arr.push(val);
}
getMax(): T {
let arr = this.arr;
let max = arr[0];
for (let i = 0; i < arr.length; i++) {
let cur = arr[i];
cur > max ? (max = cur) : void null;
}
return max;
}
}
let list = new MyList();
list.add(1);
list.add(true);
TypeScript 学习笔记 — 泛型的使用(七)的更多相关文章
- Typescript 学习笔记七:泛型
中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...
- Typescript 学习笔记六:接口
中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...
- Typescript 学习笔记五:类
中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...
- Typescript 学习笔记四:回忆ES5 中的类
中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...
- Typescript 学习笔记二:数据类型
中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...
- Typescript 学习笔记三:函数
中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...
- Typescript 学习笔记一:介绍、安装、编译
前言 整理了一下 Typescript 的学习笔记,方便后期遗忘某个知识点的时候,快速回忆. 为了避免凌乱,用 gitbook 结合 marketdown 整理的. github地址是:ts-gitb ...
- TypeScript学习笔记(八):1.5版本之后的模块和命名空间
我之前有写过TS1.5版本之前的“模块”的笔记:TypeScript学习笔记(七):模块 但是TS这里的模块和在ECMAScript 2015里的模块(即JS原生支持了模块的概念)概率出现了混淆,所以 ...
- TypeScript学习笔记(五) - 泛型
本篇将介绍在TypeScript如何使用泛型. 一.泛型方法 在TypeScript里,声明泛型方法有以下两种方式: function generics_func1<T>(arg: T): ...
- typescript学习笔记(一)---基础变量类型
作为一个前端开发者,学习新技术跟紧大趋势是必不可少的.随着2019年TS的大火,我打算利用一个月的时间学习这门语言.接下来的几篇文章是我学习TS的学习笔记,其中也会掺杂一些学习心得.话不多说,先从基础 ...
随机推荐
- PageOffice在线打开office文件通过js调用vba可实现的功能
pageoffice封装的js接口有限,某些比较复杂的设置用到的客户不多,所以没有提供直接的js方法,但是pageoffice提供了Document属性和RunMacro方法,可以调vba或直接运行宏 ...
- NumPy 分割与搜索数组详解
NumPy 分割数组 NumPy 提供了 np.array_split() 函数来分割数组,将一个数组拆分成多个较小的子数组. 基本用法 语法: np.array_split(array, indic ...
- 【题解】A18535.来自领导的烦恼
题目跳转 思路:本题可以使用动态规划或递归的方式来实现,本质上是一道01背包的变型题.假设一共有\(n\)名员工,每一位员工的技能水平用\(a[i]\)表示.要使得两个部门的员工技能总和之差最小,意思 ...
- YUV图片旋转
1.从H264视频流中解析出来的图片格式是YUV YUV旋转可以选择手工旋转,也可以利用libYUV,libYUV开启NEON指令之后可以加快处理速度 在iOS系统上,利用Accelcerate库进行 ...
- itest(爱测试)开源接口测试&敏捷测试&极简项目管理 7.1.0 发布,ui优化及bug修复
(一)itest 简介及更新说明 itest 开源敏捷测试管理,testOps 践行者,极简的任务管理,测试管理,缺陷管理,测试环境管理,接口测试,接口Mock 6合1,又有丰富的统计分析.可按测试包 ...
- numpy基础--线性代数
以下代码的前提:import numpy as np 线性代数(如矩阵乘法.矩阵分解.行列式以及其他方阵数学等)是任何数组库的重要组成部分.numpy提供了一个用于矩阵乘法的dot函数(既是一个数组方 ...
- 告别Word,用Python打造你的专业简历!
今天给大家介绍下一个在纯 python 中构建简历的实用工具,工具的连接地址https://github.com/koek67/resume-builder/blob/main/readme.md 用 ...
- 【Java面试题-基础知识03】Java线程连环问
1.Java中的线程是什么? 在Java中,线程是程序执行流的最小单元.每个Java程序都至少有一个主线程,也称为主执行线程,它是程序开始执行时自动创建的.除了主线程外,程序员还可以创建额外的线程来执 ...
- pandas、spark计算相关性系数速度对比
pandas.spark计算相关性系数速度对比 相关性计算有三种算法:pearson.spearman,kenall. 在pandas库中,对一个Dataframe,可以直接计算这三个算法的相关系数c ...
- 透过 node-exporter 彻底弄懂机器监控:01. node-exporter 框架讲解
前言 Prometheus 生态里有很多采集器负责各类监控数据的采集,其中使用最广泛的,显然是 node-exporter,负责 Linux.BSD 等系统的常规监控指标的采集,比如 CPU.内存.硬 ...