引言
Typescript(TS)已经成为了现在前端编码的主流,几乎所有现在流行的框架都在使用TS,比如Angular,React,Vue3等. TS的好处就不用多说了,虽然代码要多写点,但是在编译的时候可以提前纠错对项目的推进是非常友好的。
泛型 -- Generics
今天我们来讲一讲TS中的泛型,TS的文档如是说:
软件工程中,我们不仅要创建一致的定义良好的 API,同时也要考虑可重用性。 组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能。 在像 C# 和 Java 这样的语言中,可以使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据。 这样用户就可以以自己的数据类型来使用组件。
如果没有接触过C#或者Java语言的开发者,很难去理解这段文字。那么在我们说泛型之前,我们先举几个例子来了解一下它在实际场景中的应用。
场景一
假设有这样一个函数接收一个字符串作为参数,函数将这个参数打印出来再返回出去。
function print(params: string):string{
console.log(params);
return params;
}
看起来没什么太大问题,现在需求变了,我们还想传入的是个number类型,返回的也是number类型,这还不简单,我们再多加一个类型就好了嘛。
function print(params: string | number): string | number {
console.log(params);
return params;
}
const result: string = print(111); // 报错 Type 'string | number' is not assignable to type 'string'. Type 'number' is not assignable to type 'string'.
const result: number = print(111); //Ok
那如果需求又变了,还有可能传入的是boolen或者object怎么办,不可能还一个个添加上去了,这样不仅可维护性比较差,而且代码可读性也很差。有人说可以写any就解决了这个问题了,首先TS本就不建议写any类型,而且写any类型那就和JS没啥区别了。这时候泛型就可以很好地解决这个问题了,它可以保证函数输入和输出的一致性,
function print<T>(params: T): T {
console.log(params);
return params;
}
const result: number = print(111);
我们可以看到我们在函数名print和小括号中间插入了一个<T>的字符,这里<>就是泛型的语法,里面定义的是类型参数,常用T代替。
泛型中的T就像一个占位符、或者说一个变量,在使用的时候可以把定义的类型像参数一样传入,它可以原封不动地输出
那这个类型参数我们什么时候去指定呢,一般有两种方式:\
- 定义要使用的类型
- TS类型推断,自动推导出结果
print<string>("hello"); // 定义类型
print(123); // 类型推断
场景二
假设现在有这样一个函数,他接收一个对象和键名作为参数,该函数返回这个键对应的键值.
const getObjectValue = (obj, key) => {
return obj[key];
}
const student = {
gender: "male",
age: 12
}
getObjectValue(student, "gender");
getObjectValue(student, "name");
我们传入了两个不同的键名去调用这个函数,发现TS并没有去报错,而student并没有name属性,我们是希望它能够检测出来并报错的,现在我们就用泛型来去约束下这个函数:
const getObjectValue = <T extends Object, K extends keyof T>(obj: T, key: K): T[K] => {
return obj[key];
}
const student = {
gender: "male",
age: 12
}
getObjectValue(student, "gender"); // OK
getObjectValue(student, "name"); // 报错:Argument of type '"name"' is not assignable to parameter of type '"gender" | "age"'
整个函数定义感觉变长了好多,不用紧张,我们简单分析下就很容易理解了,首先<>里面还是定义的泛型,就是类型参数,只不过这里用逗号分开定义了两个,第一个T继承了Object类型,第二个K相当于继承了T的所有键名的集合,括号内的就不多做解释了,就是参数类型。最后冒号:后面的T[K]代表的返回值就是T对象对应的K键的键值。怎么样是不是很好理解。
小结
- 泛型是指在定义函数,接口,类的时候,不预先指定类型,而是在使用的时候再去指定.
- 泛型中的
T就像一个占位符、或者说一个变量,在使用的时候可以把定义的类型像参数一样传入,它可以原封不动地输出。 - 优点:
- 不事先指定参数类型,增加了代码的拓展性
- 不用什么联合类型,增加代码可读性
- 可以控制类型之间的约束
这篇文章简单地介绍了下泛型的定义和使用,后期还会写一些TS中一些其他的知识点, 拥抱TS已成为开发者的主流,快加入我们吧!!!欢迎点赞收藏☆!!!