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

news2024/11/15 5:09:39

泛型

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

泛型一般用在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; }



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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

中小学校园EasyCVR视频综合监管方案:构建安全、智能的校园环境

一、背景需求分析 随着科技的快速发展&#xff0c;校园安全问题日益受到社会各界的关注。尤其是在中小学校园中&#xff0c;学生的安全更是牵动着每一个家庭的心。为了更有效地保障学生的安全&#xff0c;提高校园安全管理水平&#xff0c;视频监控系统在中小学中的应用越来越…

1.10编程基础之简单排序--02:奇数单增序列

OpenJudge - 02:奇数单增序列http://noi.openjudge.cn/ch0110/02/ 描述 给定一个长度为N(不大于500)的正整数序列,请将其中的所有奇数取出,并按升序输出。 输入 共2行: 第1行为 N; 第2行为 N 个正整数,其间用空格间隔。 输出 增序输出的奇数序列,数据之间以逗号间隔。数…

华为od100问持续分享-1

我是一名软件开发培训机构老师&#xff0c;我的学生已经有上百人通过了华为OD机试&#xff0c;学生们每次考完试&#xff0c;会把题目拿出来一起交流分享。 重要&#xff1a;2024年5月份开始&#xff0c;考的都是OD统一考试&#xff08;D卷&#xff09;&#xff0c;题库已经整…

GDidees CMS v3.9.1 本地文件泄露漏洞(CVE-2023-27179)

前言 CVE-2023-27179 是一个影响 GDidees CMS v3.9.1 及更低版本的任意文件下载漏洞。这个漏洞存在于 /_admin/imgdownload.php 文件中&#xff0c;攻击者可以通过向 filename 参数传递恶意输入来下载服务器上的任意文件。 漏洞的根源在于对用户输入的 filename 参数处理不当…

对于多个表多个字段进行查询、F12查看网页的返回数据帮助开发、数据库的各种查询方式(多对多、多表查询、子查询等)。

对于多个表多个字段进行查询、F12查看网页的返回数据帮助开发、数据库的各种查询方式&#xff08;多对多、多表查询、子查询等&#xff09;。 一、 前端界面需要展现多个表的其中几个数据的多表查询。1. 三个表查询其中字段返回&#xff1a;&#xff08;用一下sql语句&#xff…

scipy库中,不同应用滤波函数的区别,以及FIR滤波器和IIR滤波器的区别

一、在 Python 中&#xff0c;有多种函数可以用于应用 FIR/IIR 滤波器&#xff0c;每个函数的使用场景和特点各不相同。以下是一些常用的 FIR /IIR滤波器应用函数及其区别&#xff1a; from scipy.signal import lfiltery lfilter(fir_coeff, 1.0, x)from scipy.signal impo…

数据结构——约瑟夫环C语言链表实现

约瑟夫环问题由古罗马史学家约瑟夫&#xff08;Josephus&#xff09;提出&#xff0c;他参加并记录了公元66—70年犹太人反抗罗马的起义。在城市沦陷之后&#xff0c;他和40名死硬的将士在附近的一个洞穴中避难。起义者表示“宁为玉碎不为瓦全”&#xff0c;约瑟夫则想“留得青…

服务器提交记录有Merge branch消除

背景&#xff1a;在共同开发分支release上&#xff0c;你提交了commit&#xff0c;push到服务器上时&#xff0c;发现有人先比你push了&#xff0c;所以你得先pull&#xff0c; 后再push&#xff0c;然而pull后自动产生了一个Merge branch的一个commit&#xff0c;这个commit本…

Floyd算法——AcWing 343. 排序

目录 Floyd算法 定义 运用情况 注意事项 解题思路 基本步骤 AcWing 343. 排序 题目描述 运行代码 代码思路 改进思路 Floyd算法 定义 Floyd算法&#xff0c;全称Floyd-Warshall算法&#xff0c;是一种用于解决图中所有顶点对之间的最短路径问题的动态规划算法。…

配置Java开发环境

Java是一种广泛使用的编程语言&#xff0c;特别是在企业应用和安卓开发中。本文将详细介绍如何在您的计算机上配置Java开发环境&#xff0c;包括安装JDK、配置环境变量以及选择和设置IDE。 一、安装Java Development Kit (JDK) JDK&#xff08;Java Development Kit&#xff0…

用JavaScript将 NCR(Numeric Character Reference)标记转换为对应字符的方法

0 &#xff0c 、&#11111……是什么鬼&#xff1f; 最近&#xff0c;要将一些网页内容复制到<textarea>文本框中作进一步处理&#xff0c;发现有些网页内容中包含&#xff0c或之类的标记&#xff0c;会被原样复制到<textarea>文本框中。 如果将这些网页内容直…

AI Agent 的发展现状、行业结构与趋势分析

Agent 来自一种哲学概念&#xff0c;是个很古老的哲学术语&#xff0c;从哲学意义上讲&#xff0c;“代理”的概念涉及实体的自主性&#xff0c;具有行使意志、做出选择和采取行动的能力&#xff0c;而不是被动地对外部刺激做出反应。后来人们将这一概念引入计算机科学领域&…

285个地级市-胡焕庸线数据

全国285个地级市-胡焕庸线数据.zip资源-CSDN文库 胡焕庸线&#xff1a;中国人口与生态的分界线 胡焕庸线&#xff0c;一条在中国地理学界具有划时代意义的分界线&#xff0c;由著名地理学家胡焕庸于1935年提出。这条线从黑龙江省的瑷珲&#xff08;现黑河市&#xff09;延伸至…

又上热搜!曝iPhone 16将支持40W快充

ChatGPT狂飙160天&#xff0c;世界已经不是之前的样子。 更多资源欢迎关注 7月9日晚&#xff0c;微博话题“iPhone16系列或将支持40W快充”上了热搜榜&#xff0c;这已经是iPhone 16系列第N次上热搜了。 据爆料&#xff0c;iPhone 16系列充电功率将提升至40W&#xff0c;并且…

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 …

书生大模型实战营(暑假场)-入门岛-第二关

目录 关卡任务 任务一 任务二 总结 关卡任务 任务一&#xff1a; 请实现一个wordcount函数&#xff0c;统计英文字符串中每个单词出现的次数。返回一个字典&#xff0c;key为单词&#xff0c;value为对应单词出现的次数。 这个算是比较简单的了&#xff0c;代码如下所示 …

C基础day8

一、思维导图 二、课后习题 #include<myhead.h> #define Max_Stu 100 //函数声明 //学生信息录入函数 void Enter_stu(int *Num_Stu,char Stu_name[][50],int Stu_score[]); //查看学生信息 void Print_stu(int Num_Stu,char Stu_name[][50],int Stu_score[]); //求出成绩…

Rust vs Go: 特点与应用场景分析

目录 介绍Rust的特点Go的特点Rust的应用场景Go的应用场景总结 介绍 Rust和Go&#xff08;Golang&#xff09;是现代编程语言中两个非常流行的选择。凭借各自的独特优势和广泛的应用场景&#xff0c;吸引了大量开发者的关注。本文将详细介绍Rust和Go的特点&#xff0c;并探讨它…

OpenCV 寻找棋盘格角点及绘制

目录 一、概念 二、代码 2.1实现步骤 2.2完整代码 三、实现效果 一、概念 寻找棋盘格角点&#xff08;Checkerboard Corners&#xff09;是计算机视觉中相机标定&#xff08;Camera Calibration&#xff09;过程的重要步骤。 OpenCV 提供了函数 cv2.findChessboardCorners…