阅读 146

typescript-泛型(typescript泛型的用途)

在软件工程领域,我们不仅要创建定义一致良好的 API,也需要同时考虑重用性,泛型就给予了这样的灵活性但又不失优雅

泛型之 Hello World

先定义如下的一个函数,这个函数会返回任何传入它的值。

function getValue(a: number): number {   return a; } 复制代码

上面我们定义的函数参数是一个数字类型的,返回值当然也是数字类型的。

假如我们需要传递一个字符串参数并返回,那么就必须再定义一个函数

function getValue(a: number): number {   return a; } function getValue1(a: string): string {   return a; } 复制代码

但是它们两个函数的功能都是一致的,只是参数的类型不一致而已。

而且假如要扩展其他数据类型的话,难道都要再写一次嘛?

或者,我们使用any类型来定义函数:

function getValue(a: any): any {   return a; } 复制代码

但是使用 any 类型就丢失了一些信息:传入的值必须与返回的值是同一种类型。因为 any 体现不出这个关系。

但是 **泛型 ** 可以定义一致的接口,同时考虑代码重用性

这里我们使用 类型变量,它是一种特殊的变量,只表示类型而不是值

字母保持一致就好,一般使用 T 表示 (Type)

function getValue<T>(a: T): T {   return a; } getValue<number>(3); getValue<string>("qzy"); 复制代码

我们把这个版本的函数叫做泛型,因为它可以适用于多个类型

我们定义了泛型函数后,可以用两种方法使用。

第一种是,传入所有的参数,包含类型参数:

getValue<string>("abc"); 复制代码

第二种方法更普遍。利用了类型推论 -- 即编译器会根据传入的参数自动地帮助我们确定 T 的类型:

getValue(1); 复制代码

使用泛型变量

使用泛型创建函数时,必须要在函数体内正确的使用这个类型

function getValue<T>(a: T): T {   console.log(a.length);   return a; } 复制代码

上面的例子中,我们想访问传入参数的 length属性。

但是这个 T 有可能是一个数字类型,而数字类型是不存在 length 属性的。因此编译器就报错了。

function getValue<T>(a: T): T {   // 类型“T”上不存在属性“length”   console.log(a.length);   return a; } 复制代码

为此我们定义一个接口来描述条件。

interface LengthProps {   length: number; } function getValue<T extends LengthProps>(a: T): T {   console.log(a.length);   return a; } getValue([1, 2]);  getValue(1); // 类型“number”的参数不能赋给类型“LengthProps”的参数 复制代码

泛型接口

泛型接口有两种方式

第一种:

interface config {   <T>(val: T): T; } // fn: config // function 后面要与接口定义的一致 let fn: config = function <T>(val: T): T {   return val; }; fn(5); 复制代码

第二种:

interface config<T> {   (val: T): T; } function configFn<T>(val: T): T {   return val; } // config<string> // = configFn let fn: config<string> = configFn; fn("qzy"); 复制代码

泛型约束-类型参数

你可以声明一个类型参数,且它被另一个类型参数所约束。

比如,现在我们想要用属性名从对象里获取这个属性,并且我们想要确保这个属性存在于对象 obj上,因此我们需要在这两个类型之间使用约束。

function getProperty<T, K>(obj: T, key: K) {   // 类型“K”无法用于索引类型“T”   return obj[key]; } let x = { a: 1, b: 2, c: 3, d: 4 }; getProperty(x,'e'); 复制代码

我们代码的意图是,通过传入一个泛型的对象,或者什么其他的变量,然后再传入另外一个泛型的变量,找到 obj 下面的 key 属性。

这个时候就你的编辑器就会报这样的错,我们传入的泛型key变量,不一定是存在于泛型obj中的属性。

为解决这一问题,我们可以使用 keyof

function getProperty<T, K extends keyof T>(obj: T, key: K) {   // 类型“K”无法用于索引类型“T”   return obj[key]; } let x = { a: 1, b: 2, c: 3, d: 4 }; getProperty(x, "b"); getProperty(x,'e'); // 类型“"e"”的参数不能赋给类型“"b" | "a" | "c" | "d"”的参数 复制代码

K extends keyof T 将两个类型变量关系起来


作者:我想知小鱼儿
链接:https://juejin.cn/post/7036763146249306149

 伪原创工具 SEO网站优化  https://www.237it.com/ 


文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐