TypeScript学习8:泛型

函数泛型

引入需求

如果我们不使用泛型

我们会这样子去实现:

function numberArray(a1:number, a2:number):number[]{return [a1, a2]
}
function stringArray(a1:string, a2:string):string[]{return [a1, a2]
}

但是如果我还需要别的类型参数呢,比如bool值等,不断像上面这样创建类似的代码会让代码非常丑且冗余

所以这里我们需要用到泛型,简而言之,泛型就是把类型当做参数

和Java中的泛型原理是一样的!

那么我们使用泛型来实现上面这个需求就很简单了

function array<T>(a:T, b:T):T[]{return [a, b]
}

只需要在函数名后面加上尖括号就可以使用泛型了

使用这个方法也非常简单,给T赋值就行了:

console.log(array(1,2))
console.log(array<number>(1,2))

(这里指定T为number类型) 

可是通常情况下,我的函数参数类型不一定只有一种,该怎么办呢

很简单,我们可以定义多种泛型

如:

function array<T,K>(a:T, b:K):(T|K)[]{return [a, b]
}console.log(array(1,"2"))
console.log(array<number, string>(1,"2"))

泛型约束

开发过程中,我们可能遇到这种情况,在泛型函数中,我们需要调用参数的.length方法,但在定义函数时,泛型具体是什么类型还没有被指定,无法确认选择的类型是否真的有length方法,这个时候我们得想办法对泛型进行约束。

就拿需要调用参数的.length方法为例,我们知道,只有string和数组类型才能调用,所以我们可以通过extend去限制泛型

function array<T extends string|any[]>(a:T, b:T):T[]{console.log(a.length)return [a, b]
}console.log(array("12334","2"))
console.log(array(["1", "33"],["2"]))

接口泛型

普通的接口函数一般是定义一些要写的变量和函数要求

interface Fun {(name: string):string
}let fun:Fun = function (name:string):string{return ""
}

但是接口里的函数也可能是泛型1函数

interface ArrType<T> {(a1: T,a2:T):T[]
}let fun:ArrType<string> = function (a1:string, a2:string):string[]{return [a1, a2]
}

 (只需要把泛型类型定义在接口后面的尖括号中,其实也可以写在内部的函数前面,像这样⬇,但是这样就只是针对于该函数的写法,并不推荐使用)

interface ArrType {<T>(a1: T,a2:T):T[]
}let fun:ArrType = function<string> (a1:string, a2:string):string[]{return [a1, a2]
}

除了接口中的方法可以使用泛型定义,属性当然也可以的

interface Info<T> {like: T
}let zhangsan: Info<string> = {like: "羽毛球"
}
let lisi: Info<string[]> = {like: ["羽毛球"]
}

 这里同样可以加上泛型约束

interface Info<T extends string|string[]> {like: T
}let zhangsan: Info<string> = {like: "羽毛球"
}
let lisi: Info<string[]> = {like: ["羽毛球"]
}

弹药注意,这里不要和接口继承搞混了,我们知道,接口也是可以继承的,它和泛型约束相似但不一样。

interface People {name?: string
}
interface Info<T extends string|string[]> extends People{like: T
}let zhangsan: Info<string> = {like: "羽毛球"
}
let lisi: Info<string[]> = {like: ["羽毛球"]
}

keyof

这里我们又有一个需求,我们需要传入一个key来调取某个对象的key属性,我们该如何去做。

我们可能会将key作为参数传进去,再获取对象的key属性:

interface Info {name: stringage: number
}let zhangsan:Info = {name:"zhangsan",age: 21
}function getInfoValue(info:Info, key: string):void{// 这个时候,这里会报错,原因是因为传入的这个key,有可能不是Info的属性console.log(info[key])
}getInfoValue(zhangsan, "name")

(!typescript的类型检查会帮你避免很多问题哦)

当key属性并不在Info中时,会报错!

 上面这种方法没办法解决,我们可以使用keyof来实现。

interface Info {name: stringage: number
}let zhangsan:Info = {name:"zhangsan",age: 21
}function getInfoValue(info:Info, key: keyof Info):void{console.log(info[key])
}getInfoValue(zhangsan, "name")
getInfoValue(zhangsan, "age")
getInfoValue(zhangsan, "age1") // 不满足keyof的校验,会报错

(key : keyof Info)限定了传入的key必须是Info里面的属性!

 再结合前面学习的泛型,这里我们可以进行优化:

interface Info {name: stringage: number
}let zhangsan:Info = {name:"zhangsan",age: 21
}function getInfoValue<T extends keyof Info>(info:Info, key: T):Info[T]{return info[key]
}getInfoValue(zhangsan, "name")
getInfoValue(zhangsan, "age")

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

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

相关文章

定制自己的 AI 角色CustomChar;AI知识点和面试题;提高llama 3 的微调速度Unsloth

✨ 1: CustomChar 允许你创建和定制自己的 AI 角色 CustomChar 是一个开源项目&#xff0c;它允许你创建和定制自己的 AI 角色。无论是游戏中的角色&#xff0c;还是个人的虚拟助手&#xff08;比如电脑上的 JARVIS&#xff09;&#xff0c;甚至是在线教育体验中的虚拟朋友或…

vite和webpacke的常规配置

文章目录 1、vite和webpacke的区分2、vite的常规配置介绍主要部分介绍vite基本配置示例 3、webpacke的常规配置介绍主要部分介绍Webpack 基本配置示例 1、vite和webpacke的区分 相同点&#xff1a; 都是构建工具&#xff0c;用于资源打包 &#xff1b; 都有应用到摇树原理 tre…

Rust Tracing 入门

Tracing 是一个强大的工具&#xff0c;开发人员可以使用它来了解代码的行为、识别性能瓶颈和调试问题。 Rust 是一种以其性能和安全保证而闻名的语言&#xff0c;在它的世界中&#xff0c;跟踪在确保应用程序平稳高效运行方面发挥着至关重要的作用。 在本文中探讨Tracing 的概…

OpenStack云计算(十一)——OpenStack网络管理,验证OpenStack网络资源模型,验证来巩固和加深对OpenStack网络资源模型的理解

项目实训一 【实训题目】 验证OpenStack网络资源模型 【实训目的】 通过验证来巩固和加深对OpenStack网络资源模型的理解。 【实训准备】 &#xff08;1&#xff09;复习Neutron网络资源模型。 &#xff08;2&#xff09;重点理解网络、子网、端口和路由器的概念。 【实…

数学建模--深入剖析线性规划(模型全方位解读+代码分析)

1.简介 &#xff08;1&#xff09;线性规划三要素 &#xff08;2&#xff09;模型适用赛题 2.典例讲解 &#xff08;1&#xff09;问题分析 目标函数是净收益尽可能大&#xff0c;风险尽可能小&#xff1b; 约束条件是交易费的分段函数&#xff0c;以及每一笔投资都是非负数&am…

海康Visionmaster-常见问题排查方法-启动阶段

VM试用版启动时&#xff0c;弹窗报错&#xff1a;加密狗未安装或检测异常&#xff1b;  问题原因&#xff1a;安装VM 的时候未选择软加密&#xff0c;选择了加密狗驱动&#xff0c;此时要使用软授权就出现了此现象。  解决方法&#xff1a; ① 首先确认软加密驱动正确安装…

面向对象练习坦克大兵游戏

游戏玩家&#xff08;名称&#xff0c;生命值&#xff0c;等级&#xff09;&#xff0c;坦克&#xff0c;大兵类&#xff0c;玩家之间可以相互攻击&#xff0c;大兵拥有武器&#xff0c;用枪弹和反坦克炮弹&#xff0c;造成攻击不同&#xff0c;坦克攻击值固定&#xff0c;请设…

常见的数据抽取工具对比

1.什么是ETL? ETL&#xff0c;是英文Extract-Transform-Load的缩写&#xff0c;用来描述将数据从来源端经过抽取&#xff08;extract&#xff09;、转换&#xff08;transform&#xff09;、加载&#xff08;load&#xff09;至目的端的过程&#xff0c;是数据仓库的生命线。 …

用Python将原始边列表转换为邻接矩阵

&#x1f47d;发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 在图论和网络分析中&#xff0c;图是一种非常重要的数据结构&#xff0c;它由节点&#xff…

Pytorch:张量的梯度计算

目录 一、自动微分简单介绍1、基本原理2、梯度计算过程3、示例&#xff1a;基于 PyTorch 的自动微分a.示例详解b.梯度计算过程c.可视化计算图 4、总结 二、为什么要计算损失&#xff0c;为何权重更新是对的&#xff1f;1、梯度下降数学原理2、梯度上升 三、在模型中使用自动微分…

(C++) 树状数组

目录 一、介绍 二、一维树状数组 2.1 区间长度 2.2 前驱和后继 2.3 查询前缀和 2.4 点更新 三、一维数组的实现 3.1 区间长度函数 3.2 前缀和 3.3 插入/更新 3.4 封装成类 一、介绍 树状数组&#xff08;Binary Indexed Tree&#xff0c;BIT&#xff09;&#xff0c;又称为 …

YOLOv8-Pose推理详解及部署实现

文章转自&#xff1a;YOLOv8-Pose推理详解及部署实现 注意事项 一、2024/1/10更新 修改第 4 部分 YOLOv8-Pose 推理中后处理 iou 计算代码&#xff0c;原代码存在问题&#xff0c;原代码如下&#xff1a; def iou(box1, box2):def area_box(box):return (box[2] - box[0]) …