【TypeScript】TS进阶-泛型(八)
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
🐱个人主页不叫猫先生
🙋♂️作者简介前端领域新星创作者、阿里云专家博主专注于前端各领域技术共同学习共同进步一起加油呀
💫系列专栏vue3从入门到精通、TypeScript从入门到实践
📢资料领取前端进阶资料以及文中源码可以找我免费领取
🔥社群招募博主建立了一个前端交流群汇集了各路大神期待你的加入(文末有我wx或者私我)
目录
专栏介绍
TypeScript从入门到实践专栏是博主在学习和工作过程中的总结实用性非常强欢迎订阅哦学会TS不迷路。
TS系列 | 标题 |
---|---|
基础篇 | TS入门一 |
基础篇 | TS类型声明二 |
基础篇 | TS接口类型三 |
基础篇 | TS交叉类型&联合类型四 |
基础篇 | TS类型断言五 |
基础篇 | TS类型守卫六 |
进阶篇 | TS函数重载七 |
进阶篇 | TS泛型八 |
进阶篇 | TS装饰器九 |
泛型
软件工程中我们不仅要创建一致的定义良好的API同时也要考虑可重用性。 组件不仅能够支持当前的数据类型同时也能支持未来的数据类型这在创建大型系统时为你提供了十分灵活的功能。
在像C#和Java这样的语言中可以使用泛型来创建可重用的组件一个组件可以支持多种类型的数据。 这样用户就可以以自己的数据类型来使用组件。 ——摘自官方文档
为什么要引入泛型的概念呢其实简单来讲就是为了实现复用让模块可以支持多种类型数据 让类型声明和值一样可以被赋值和传递。
泛型是什么呢它可以说是一种类型占位符也可以说是类型变量需要注意的是它一种特殊的变量只用于表示类型而不是值。我们在定义函数、接口或类的时候不预先指定具体类型而是在使用的时候再指定类型先站住位置再说保证了输入输出保持一致的问题。
这里举个例子说明为什么要使用泛型。我们写一个函数实现返回传递参数的值并且打印这个值参数类型为string
返回值类型也是string
保证输入输出保持一致。
function result(val:string):string {
console.log(val)
return val
}
当然我们可以用any
来定义变量类型如下
function result(val:any):any {
console.log(val)
return val
}
因为any
是任意类型所以我们不能保证输入输出保持一致比如参数类型是number返回的却是string另外最好不要用any。
如果我参数类型是number
返回值类型也是number我们就需要再写一个函数是不是有点重复了如果参数类型返回值类型可以是个类型变量可以根据传递的值来判断是不是就方便很多啦比如下面写的这个例子看不懂没关系下面详细解析
function result<T>(val:T):T {
console.log(val)
return val
}
result(<striing>"zhangsan")
给result
函数添加一个类型变量T
T
需要写在<>
T
帮助我们捕获用户传入的类型比如number 之后我们再次使用了 T当做返回值类型。这样参数类型和返回值类型就相同啦。编译为JS的代码如下
function result(val) {
console.log(val);
return val;
}
result("zhangsan");
下面详细讲解下用法。
1、常用的泛型变量
- TType 代表类型定义泛型时通常作为第一个类型变量名称
- KKey表示对象中的键类型
- U表示对象中的键类型
- VValue表示对象中的值类型
- EElement表示元素或者节点类型
2、具体用法
1函数中多参数使用
function startClass <T, U>(name: T, score: U) : T {
return name + score;
}
console.log(startClass<String, Number>("zhangsan", 5));//zhangsan5
2接口类型中使用
interface Class{
<T,U>(name:T,score:U):T
}
let func = function <T,U>(name:T,score:U):T{
return name + ':'+ score
}
func('zhangsan',3)//编译器自动识别参数类型作为泛型的类型
3类中使用
class Animal<T> {
name:T;
constructor(name: T){
this.name = name;
}
get<T>(say:T) {
console.log(say)
}
}
let animal = new Animal('cat');
animal.get('pig')//pig
3、泛型默认类型
语法<T = default type>
type Class<T> = {
target: T;
type: string;
}
4、泛型约束
我们之间使用属性方法但是不知道类型就会报错所以需要对参数类型进行约束。
function result<T>(val:T):T {
console.log(val.length)
return val
}
result(<string>"zhangsan")
//这种写法也可以的哦
//result<string>("zhangsan")
怎么进行约束呢先用type
声明一个变量类型让类型变量T
继承接口Class
此时代码就不会报错啦。
type Class = string;
function result<T extends Class>(val:T):T {
console.log(val.length)
return val
}
result(<string>"zhangsan")
当然我们也可以使用接口类型让变量类型T
继承接口Class具体如下
interface Class{
name:string,
age:number
}
function result<T extends Class>(val:T):T {
console.log(val.name)
return val
}
result({name:"zhangsan",age:10})
//如果参数重不写age的话就会报错
//类型“{ name: string; }”的参数不能赋给类型“Class”的参数。
//类型 "{ name: string; }" 中缺少属性 "age"但类型 "Class" 中需要该属性。
result({name:"zhangsan"})
如果不对变量类型进行约束的话还是会报错滴如下
5、泛型工具类型
后续更新泛型工具类型