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

打印 上一主题 下一主题

主题 511|帖子 511|积分 1533

泛型

泛型,动态类型,是一个初始化不明确的类型,类似于函数中的形参(不明确参数值),
泛型一样寻常用在function定义函数时动态束缚类型,和type定义类型时动态束缚类型,
泛型一样寻常使用恣意的大写字母规定,同名的泛型表示同一种类型
泛型在实例化使用后(定义了明确类型之后,本次实例化使用就只能表示这种类型)

泛型的使用示例

  1. // 将参数合成数组
  2. function add<T>(a:T,b:T):Array<T>{
  3.   return [a,b];
  4. }
  5. add(1,2) //这里的T被固定成number
  6. add('a','b') //这里的T被固定成string
  7. add(true,false)// 这里的T被固定成boolean
复制代码
这里实现了一个数组合成的函数,它接受两个同类型的参数,返回这个类型的数组,
在这个案例中,接受了参数类型并不明确,只是要求两个参数的类型和返回值的类型要一致,至于具体是什么类型并没有强制要求,
于是就可以设置一个泛型T来规定,这里T表示一种类型,在使用函数设置了参数后,T就被固定类型了,此时整个函数中所有的T都时同一种类型,例如上面的add(1,2),这个add里面的T就被固定(替换)成了number类型,

泛型的特点

   1. 泛型可以指定多个,如<T,U>
  2. 泛型可以指定默认类型,如<T=number>
  3. 泛型可以指定联合类型
   
  1. type Ab<T,U=object> = number | string | T | U;
  2. let ab:Ab<boolean>;
  3. ab =20;
  4. ab ='a';
  5. ab =true;
  6. ab = {};
复制代码
以上ab变量可以被设置成number,string,object,和Boolean类型中的恣意一种,
Ab类型中U泛型有默认值,不设置的情况下默以为object,而T没有默认值,必须设置类型

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

有了泛型,对于一些未知类型数据的操作就方便很多,泛型最常用的地方就是ajax网络请求,网络请求一样寻常是会用来请求多种数据的,要标志出每种数据(联合所有可能的类型)不太容易,这个时间就可以使用泛型,当请求效果出来后,泛型被固定,就可以获得类型检测了
  1. // 封装模拟axios的get方法, 返回一个Promise,Promise成功时返回请求结果
  2. const axios = {
  3.   get<T>(url:string):Promise<T>{
  4.     return new Promise((resolve,reject)=>{
  5.       let xhr:XMLHttpRequest = new XMLHttpRequest();
  6.       xhr.open('GET',url);
  7.       xhr.onload = ()=>{
  8.         if(xhr.status >= 200 && xhr.status < 300){
  9.           resolve(JSON.parse(xhr.response));
  10.         }
  11.       }
  12.       xhr.send();
  13.     })
  14.   }
  15. }
  16. interface Data{//指定返回数据的类型,否则对于不明确的类型,无法固定泛型,默认会定为unknow
  17.   code:number,
  18.   msg:string
  19. }
  20. axios.get<Data>('./msg.json').then(res=>{
  21.   console.log(res,res.code,res.msg);
  22. });
复制代码


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

泛型束缚:减少泛型的范围
泛型可以指定能接受的类型,使得泛型只能固定成指定的类型
  1. interface Len{
  2.   length:number
  3. }
  4. // T只接受有length属性的类型
  5. function getLen<T extends Len>(parmas:T):number{
  6.   return parmas.length;
  7. }
  8. getLen('abc');//string类型有length属性
  9. getLen([1,2,3]);//数组类型有length属性
  10. getLen({length:10});//有length属性的对象
复制代码
以上是获取参数的length属性,使用extends束缚了T,T类型是有length属性的类型,表示参数parmas的类型中需要有length属性,

keyof

keyof:获取对象的key
泛型束缚常常会使用属性,来束缚某种类型需要这个属性,使用keyof可以获取到对象的属性
  1. // keyof:获取对象的key
  2. let obj = {
  3.   name:'a',
  4.   age:10
  5. }
  6. // 获取obj类型的key的类型
  7. type O = keyof typeof obj;//O的类型为'name'|'age'
  8. function getValue<T extends object,K extends keyof T>(obj:T,key:K){
  9.   // T限制为对象,K限制为T的key
  10.   return obj[key];
  11. }
  12. getValue(obj,'name');//name是obj的key
  13. getValue(obj,'age');//age是obj的key
复制代码
以上的getValue函数中T被束缚成只能是对象类型,K被束缚成是对象的 属性
keyof的扩展用法
  1. // keyof的扩展用法
  2. interface Obj{
  3.   name:string,
  4.   age:number
  5. }
  6. // 使用keyof 获取接口类型的属性,并重新对属性定义类型规则,在赋给新属性
  7. // 这样就实现了基于已有类型,创建新的类型,(相当于类型函数,对类型进行操作)
  8. type Options<T extends object> = {
  9.   [K in keyof T]?:T[K]
  10. }
  11. //这里相当于变成了可选属性的Obj类型,Obj替代了T
  12. type L = Options<Obj>;//L的类型为{ name?:string; age?:number; }
复制代码
以上使用了keyof,遍历了束缚成对象类型的泛型T的属性,并将属性接受值的类型修改成了可选?:,再赋值给Options类型,
这里实现了一个类似函数的效果,可以把Options看成是一个‘类型函数’,将传入的类型属性全部修改成可选,


总结

   

  • 泛型的存在让ts的类型变得非常机动,使类型变得可以修改,可以变化不在固定死板;
  • 学习了泛型之后,对于ts类型的明确应该更加深入,ts类型实在就相当于一个特别的值,这个值使专门用来束缚变量的值,
  • 值可以被类型束缚,类型也是一个值,类型也可以被类型束缚,
  • 类型是一个隐式的值,它不会影响代码的效果,它会束缚代码的执行,再执行前将代码不公道的类型错误清除出来;同时在编辑代码时,提示这种类型变量的具有的属性,让整个代码更加具有逻辑性
   完整代码展示

  1. // 泛型,动态类型,// 定义函数时,对于未知的返回值和参数类型,可以使用泛型,在使用函数时,会将动态类型固定,// 定义类型时, 对于未知的类型,可以使用泛型,在给泛型的变量赋值时,会将动态类型固定// 同名的泛型表示是同一种类型,在固定类型后,同名泛型也会被相同的类型固定// 将参数合成数组
  2. function add<T>(a:T,b:T):Array<T>{
  3.   return [a,b];
  4. }
  5. add(1,2) //这里的T被固定成number
  6. add('a','b') //这里的T被固定成string
  7. add(true,false)// 这里的T被固定成boolean// 泛型的特点// 1. 泛型可以指定多个,如<T,U>// 2. 泛型可以指定默认类型,如<T=number>// 3. 泛型可以指定联合类型type Ab<T,U=object> = number | string | T | U;
  8. let ab:Ab<boolean>;
  9. ab =20;
  10. ab ='a';
  11. ab =true;
  12. ab = {};// 封装模拟axios的get方法, 返回一个Promise,Promise成功时返回请求结果
  13. const axios = {
  14.   get<T>(url:string):Promise<T>{
  15.     return new Promise((resolve,reject)=>{
  16.       let xhr:XMLHttpRequest = new XMLHttpRequest();
  17.       xhr.open('GET',url);
  18.       xhr.onload = ()=>{
  19.         if(xhr.status >= 200 && xhr.status < 300){
  20.           resolve(JSON.parse(xhr.response));
  21.         }
  22.       }
  23.       xhr.send();
  24.     })
  25.   }
  26. }
  27. interface Data{//指定返回数据的类型,否则对于不明确的类型,无法固定泛型,默认会定为unknow
  28.   code:number,
  29.   msg:string
  30. }
  31. axios.get<Data>('./msg.json').then(res=>{
  32.   console.log(res,res.code,res.msg);
  33. });// 泛型束缚:减少泛型的范围// 泛型可以指定能接受的类型,使得泛型只能固定成指定的类型interface Len{
  34.   length:number
  35. }
  36. // T只接受有length属性的类型
  37. function getLen<T extends Len>(parmas:T):number{
  38.   return parmas.length;
  39. }
  40. getLen('abc');//string类型有length属性
  41. getLen([1,2,3]);//数组类型有length属性
  42. getLen({length:10});//有length属性的对象// keyof:获取对象的key
  43. let obj = {
  44.   name:'a',
  45.   age:10
  46. }
  47. // 获取obj类型的key的类型
  48. type O = keyof typeof obj;//O的类型为'name'|'age'
  49. function getValue<T extends object,K extends keyof T>(obj:T,key:K){
  50.   // T限制为对象,K限制为T的key
  51.   return obj[key];
  52. }
  53. getValue(obj,'name');//name是obj的key
  54. getValue(obj,'age');//age是obj的key// keyof的扩展用法
  55. interface Obj{
  56.   name:string,
  57.   age:number
  58. }
  59. // 使用keyof 获取接口类型的属性,并重新对属性定义类型规则,在赋给新属性
  60. // 这样就实现了基于已有类型,创建新的类型,(相当于类型函数,对类型进行操作)
  61. type Options<T extends object> = {
  62.   [K in keyof T]?:T[K]
  63. }
  64. //这里相当于变成了可选属性的Obj类型,Obj替代了T
  65. type L = Options<Obj>;//L的类型为{ name?:string; age?:number; }
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

花瓣小跑

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表