ts语法---泛型和泛型约束

泛型

泛型,动态类型,是一个初始化不明确的类型,类似于函数中的形参(不明确参数值),

泛型一般用在function定义函数时动态约束类型,和type定义类型时动态约束类型,

泛型一般使用任意的大写字母规定,同名的泛型表示同一种类型

泛型在实例化使用后(定义了明确类型之后,本次实例化使用就只能表示这种类型)

泛型的使用示例

// 将参数合成数组
function add<T>(a:T,b:T):Array<T>{
  return [a,b];
}

add(1,2) //这里的T被固定成number
add('a','b') //这里的T被固定成string
add(true,false)// 这里的T被固定成boolean

这里实现了一个数组合成的函数,它接受两个同类型的参数,返回这个类型的数组,

在这个案例中,接受了参数类型并不明确,只是要求两个参数的类型和返回值的类型要一致,至于具体是什么类型并没有强制要求,

于是就可以设置一个泛型T来规定,这里T表示一种类型,在使用函数设置了参数后,T就被固定类型了,此时整个函数中所有的T都时同一种类型,例如上面的add(1,2),这个add里面的T就被固定(替换)成了number类型,

泛型的特点

1. 泛型可以指定多个,如<T,U>

2. 泛型可以指定默认类型,如<T=number>

3. 泛型可以指定联合类型

 

type Ab<T,U=object> = number | string | T | U;

let ab:Ab<boolean>;

ab =20;
ab ='a';
ab =true;
ab = {};

以上ab变量可以被设置成number,string,object,和Boolean类型中的任意一种,

Ab类型中U泛型有默认值,不设置的情况下默认为object,而T没有默认值,必须设置类型

使用泛型封装模拟axios的get方法

有了泛型,对于一些未知类型数据的操作就方便很多,泛型最常用的地方就是ajax网络请求,网络请求一般是会用来请求多种数据的,要标记出每种数据(联合所有可能的类型)不太容易,这个时候就可以使用泛型,当请求结果出来后,泛型被固定,就可以获得类型检测了

// 封装模拟axios的get方法, 返回一个Promise,Promise成功时返回请求结果

const axios = {
  get<T>(url:string):Promise<T>{
    return new Promise((resolve,reject)=>{
      let xhr:XMLHttpRequest = new XMLHttpRequest();
      xhr.open('GET',url);
      xhr.onload = ()=>{
        if(xhr.status >= 200 && xhr.status < 300){
          resolve(JSON.parse(xhr.response));
        }
      }
      xhr.send();
    })
  }
}

interface Data{//指定返回数据的类型,否则对于不明确的类型,无法固定泛型,默认会定为unknow
  code:number,
  msg:string
}

axios.get<Data>('./msg.json').then(res=>{
  console.log(res,res.code,res.msg);
});

这样请求不同的数据时只要修改Data的类型而不需要修改get函数 ,增强了函数的通用性

泛型约束

泛型约束:减少泛型的范围

泛型可以指定能接受的类型,使得泛型只能固定成指定的类型

interface Len{
  length:number
}

// T只接受有length属性的类型
function getLen<T extends Len>(parmas:T):number{
  return parmas.length;
}

getLen('abc');//string类型有length属性
getLen([1,2,3]);//数组类型有length属性
getLen({length:10});//有length属性的对象

以上是获取参数的length属性,使用extends约束了T,T类型是有length属性的类型,表示参数parmas的类型中需要有length属性,

keyof

keyof:获取对象的key

泛型约束常常会使用属性,来约束某种类型需要这个属性,使用keyof可以获取到对象的属性

// keyof:获取对象的key

let obj = {
  name:'a',
  age:10
}

// 获取obj类型的key的类型
type O = keyof typeof obj;//O的类型为'name'|'age'

function getValue<T extends object,K extends keyof T>(obj:T,key:K){
  // T限制为对象,K限制为T的key
  return obj[key];
}

getValue(obj,'name');//name是obj的key
getValue(obj,'age');//age是obj的key

以上的getValue函数中T被约束成只能是对象类型,K被约束成是对象的 属性

keyof的扩展用法

// keyof的扩展用法

interface Obj{
  name:string,
  age:number
}

// 使用keyof 获取接口类型的属性,并重新对属性定义类型规则,在赋给新属性
// 这样就实现了基于已有类型,创建新的类型,(相当于类型函数,对类型进行操作)

type Options<T extends object> = {
  [K in keyof T]?:T[K]
}

//这里相当于变成了可选属性的Obj类型,Obj替代了T
type L = Options<Obj>;//L的类型为{ name?:string; age?:number; }

以上使用了keyof,遍历了约束成对象类型的泛型T的属性,并将属性接受值的类型修改成了可选?:,再赋值给Options类型,

这里实现了一个类似函数的效果,可以把Options看成是一个‘类型函数’,将传入的类型属性全部修改成可选,

总结

  1. 泛型的存在让ts的类型变得非常灵活,使类型变得可以修改,可以变化不在固定死板;
  2. 学习了泛型之后,对于ts类型的理解应该更加深入,ts类型其实就相当于一个特殊的值,这个值使专门用来约束变量的值,
  3. 值可以被类型约束,类型也是一个值,类型也可以被类型约束,
  4. 类型是一个隐式的值,它不会影响代码的结果,它会约束代码的执行,再执行前将代码不合理的类型错误排除出来;同时在编辑代码时,提示这种类型变量的具有的属性,让整个代码更加具有逻辑性

 完整代码展示

// 泛型,动态类型,
// 定义函数时,对于未知的返回值和参数类型,可以使用泛型,在使用函数时,会将动态类型固定,
// 定义类型时, 对于未知的类型,可以使用泛型,在给泛型的变量赋值时,会将动态类型固定
// 同名的泛型表示是同一种类型,在固定类型后,同名泛型也会被相同的类型固定

// 将参数合成数组
function add<T>(a:T,b:T):Array<T>{
  return [a,b];
}

add(1,2) //这里的T被固定成number
add('a','b') //这里的T被固定成string
add(true,false)// 这里的T被固定成boolean


// 泛型的特点
// 1. 泛型可以指定多个,如<T,U>
// 2. 泛型可以指定默认类型,如<T=number>
// 3. 泛型可以指定联合类型

type Ab<T,U=object> = number | string | T | U;

let ab:Ab<boolean>;

ab =20;
ab ='a';
ab =true;
ab = {};

// 封装模拟axios的get方法, 返回一个Promise,Promise成功时返回请求结果

const axios = {
  get<T>(url:string):Promise<T>{
    return new Promise((resolve,reject)=>{
      let xhr:XMLHttpRequest = new XMLHttpRequest();
      xhr.open('GET',url);
      xhr.onload = ()=>{
        if(xhr.status >= 200 && xhr.status < 300){
          resolve(JSON.parse(xhr.response));
        }
      }
      xhr.send();
    })
  }
}

interface Data{//指定返回数据的类型,否则对于不明确的类型,无法固定泛型,默认会定为unknow
  code:number,
  msg:string
}

axios.get<Data>('./msg.json').then(res=>{
  console.log(res,res.code,res.msg);
});


// 泛型约束:减少泛型的范围
// 泛型可以指定能接受的类型,使得泛型只能固定成指定的类型

interface Len{
  length:number
}

// T只接受有length属性的类型
function getLen<T extends Len>(parmas:T):number{
  return parmas.length;
}

getLen('abc');//string类型有length属性
getLen([1,2,3]);//数组类型有length属性
getLen({length:10});//有length属性的对象

// keyof:获取对象的key

let obj = {
  name:'a',
  age:10
}

// 获取obj类型的key的类型
type O = keyof typeof obj;//O的类型为'name'|'age'

function getValue<T extends object,K extends keyof T>(obj:T,key:K){
  // T限制为对象,K限制为T的key
  return obj[key];
}

getValue(obj,'name');//name是obj的key
getValue(obj,'age');//age是obj的key

// keyof的扩展用法

interface Obj{
  name:string,
  age:number
}

// 使用keyof 获取接口类型的属性,并重新对属性定义类型规则,在赋给新属性
// 这样就实现了基于已有类型,创建新的类型,(相当于类型函数,对类型进行操作)

type Options<T extends object> = {
  [K in keyof T]?:T[K]
}

//这里相当于变成了可选属性的Obj类型,Obj替代了T
type L = Options<Obj>;//L的类型为{ name?:string; age?:number; }



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

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

相关文章

Jenkins教程-18-常用插件-description-setter

上一小节我们学习了Jenkin常用插件Environment Injector的使用方法&#xff0c;本小节我们讲解一下Jenkin常用插件description-setter的使用方法。 在某些情况下&#xff0c;用户可能希望根据构建过程中的某些关键信息来自定义构建的描述&#xff0c;比如部署的用户信息、提交…

​李白一生的过往轨迹矢量地图

今天我们来看一下“天子呼来不上船&#xff0c;自称臣是酒中仙”大诗人李白过往轨迹&#xff0c;看看他一生都去过哪些地方&#xff1f; 我们将李白一生去过的地方搜集整理了一份矢量地图&#xff0c;有需要请在文末查看该数据的领取方法。 李白一生的过往轨迹 李白&#xf…

stm32按键设置闹钟数进退位不正常?如何解决

&#x1f3c6;本文收录于《CSDN问答解惑-专业版》专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收…

JavaScript-日期对象

日期对象 作用&#xff1a;用来表示时间的对象 获取当前时间 const datenew Date();console.log(date);可以得到日期对象&#xff0c;里面的属性有星期&#xff0c;年月日&#xff0c;时分秒 获取指定时间 const datenew Date(2023-05-01);console.log(date); 获取时间戳 时间…

Deepspeed : AttributeError: ‘DummyOptim‘ object has no attribute ‘step‘

题意&#xff1a;尝试在一个名为 DummyOptim 的对象上调用 .step() 方法&#xff0c;但是这个对象并没有定义这个方法 问题背景&#xff1a; I want to use deepspeed for training LLMs along with Huggingface Trainer. But when I use deepspeed along with trainer I get …

实习记录3

1.Mybaits懒加载 MyBatis 延迟加载&#xff08;懒加载&#xff09;一篇入门-腾讯云开发者社区-腾讯云 (tencent.com) 2.高级映射 106-高级映射之多对一映射第一种方式_哔哩哔哩_bilibili 3.TableId(type IdType.INPUT) Mybatis-plus 主键生成策略_mybatis-plus 自增主键等于…

和鲸科技荣耀入选2024 H1 「中国最具价值 AGI 创新机构 TOP 50」

以下文章来源于Founder Park&#xff0c;作者Founder Par 大模型的盛宴&#xff0c;不应该只属于那些无数光环加身的算法天才们。 模型的冰山一角下&#xff0c;是应用层的暗流涌动&#xff0c;这是一个更庞大&#xff0c;也更隐秘的蓝海。但发掘这一切的前提是&#xff0c;所…

redis哨兵模式搭建

先搭建主从结构 当需要运行多个Redis实例时&#xff0c;可以通过为每个实例使用不同的配置文件的方式来实现。 复制redis目录下的redis.conf文件将其重命名为redis6380.conf和redis6381.conf&#xff0c;或者将其放到单独文件夹中&#xff0c;这里为了偷懒&#xff0c;简单实现…

使用 MinIO 赢得 RAG 权利

人们常说&#xff0c;在人工智能时代&#xff0c;数据是你的护城河。为此&#xff0c;构建生产级 RAG 应用程序需要合适的数据基础架构来存储、版本控制、处理、评估和查询构成专有语料库的数据块。由于 MinIO 采用数据优先的 AI 方法&#xff0c;因此对于此类项目&#xff0c;…

TotalSegmentator---针对CT/MRI数据的自动分割

很高兴在雪易的CSDN遇见你 VTK技术爱好者 QQ&#xff1a;870202403 公众号&#xff1a;VTK忠粉 前言 本文分享开源软件TotalSegmentator&#xff0c;该开源项目针对CT/MRI数据类型&#xff0c;对主要的解剖学结构进行自动分割&#xff0c;并且被集成到MITK中。希望对各…

Global Mapper:地理信息的温柔探索

引言 在这纷繁复杂的世界里&#xff0c;地理信息系统&#xff08;GIS&#xff09;如同一把利器&#xff0c;帮助我们剖析、理解和改造这个世界。而在众多GIS软件中&#xff0c;Global Mapper无疑是其中的佼佼者。作为一款功能全面且易于使用的GIS应用程序&#xff0c;Global M…

springboot养老院管理系统-计算机毕业设计源码00010

摘要 本文介绍了一种基于Spring Boot框架的养老院管理系统的设计与实现。该系统旨在帮助养老院管理者更有效地管理机构内的各项事务&#xff0c;并提供更好的服务于老年人。系统的设计考虑了养老院管理的特殊需求&#xff0c;包括系统用户、老人信息管理、服务分类管理、医疗服…

谷歌个人开发者账号14天封测审核通过技巧,你还不知道吗?

众所周知&#xff0c;目前在Google play应用商店上架应用已经不是那么容易了&#xff0c;谷歌各种政策的更新以及审核系统的升级&#xff0c;给开发者们带来了不少挑战。 尤其针对个人开发者账号需要20人连续14天的封测的要求&#xff0c;周期长&#xff0c;且随着政策执行力度…

[Vulnhub] IMF File Upload BypassBuffer Overflow

信息收集 IP AddressOpening Ports192.168.8.103TCP:80 $ nmap -p- 192.168.8.103 --min-rate 1000 -sC -sV PORT STATE SERVICE VERSION 80/tcp open http Apache httpd 2.4.18 ((Ubuntu)) |_http-title: IMF - Homepage |_http-server-header: Apache/2.4.18 (Ubunt…

揭秘!chatGPT核心技术应用

2022年11月30日&#xff0c;可能将成为一个改变人类历史的日子——美国人工智能开发机构OpenAI推出了聊天机器人ChatGPT-3.5&#xff0c;将人工智能的发展推向了一个新的高度。2023年11月7日&#xff0c;OpenAI首届开发者大会被称为“科技界的春晚”&#xff0c;吸引了全球广大…

个人面试总结

写在前面&#xff1a;以下是自己在拟录用后回顾总结的了一下当时面试题目&#xff0c;把标答写了出来&#xff0c;供以后复习所使用&#xff0c;希望大家理性食用~~ 预祝大家都能找到心仪的工作 笔试题目&#xff1a; 1.1. java中Collection和Collections的区别 Collection…

怎样将aac转换mp3格式?推荐四个aac转MP3的方法

怎样将aac转换mp3格式&#xff1f;当需要将aac格式音频转换为MP3格式时&#xff0c;有几种方法可以轻松实现这一目标。MP3是一种广泛支持的音频格式&#xff0c;几乎所有设备和平台都能播放MP3文件&#xff0c;包括各种音乐播放器、手机、平板电脑和汽车音响系统。而且它也提供…

极狐Gitlab使用(1)

目录 续接上篇&#xff1a;极狐Gitlab安装部署-CSDN博客 1. 关闭注册功能 2. 创建群组 3. 创建用户 5. 邀请成员到群组 6. 设置导入导出项目源 7. 通过gitee导入库 8. 通过仓库URL导入 9. 自创建项目 10. 默认分支main的权限 11. 使用普通用户进入自建库 12. 创建用…

传统的springboot项目中,如何进行添加自定义静态资源访问路径实现对静态资源的访问?

如何配置可以实现在浏览器中配置路径实现对resource资源路径下的index.html个性化定制访问路径 要在Spring Boot项目中配置使特定前缀访问静态资源&#xff0c;可以在application.yml文件中配置路径映射。以下是一个示例配置&#xff1a; 打开你的application.yml文件&#xf…

N6 word2vec文本分类

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊# 前言 前言 上周学习了训练word2vec模型&#xff0c;这周进行相关实战 1. 导入所需库和设备配置 import torch import torch.nn as nn import torchvision …