20. TypeScript 类中泛型(难点)
上节我们学习了在函数(方法)中使用泛型的基本语法,这节在看看类中泛型的使用方法。
编写一个基本类
为了下面的教学演示,所以我先编写一个基本的类SelectGirl,在类的构造函数中(constructor)需要传递一组女孩的名称,然后再通过下边展现女孩的名称,代码如下:
class SelectGirl {
constructor(private girls: string[]) {}
getGirl(index: number): string {
return this.girls[index];
}
}
const selectGirl = new SelectGirl(["小红", "小丽", "小影"]);
console.log(selectGirl.getGirl(1));
写完后,我们可以在终端中使用ts-node Demo.ts进行预览,可以看到控制台中输出了小丽的名字。学到现在你写这样的一个类应该是非常容易的了。
现在问题来了,比如现在更好的保护小姐姐,这些小姐姐使用编号啦,那我们程序要如何修改。需要写成下面的样子,这时候我们代码看起来就没有那么优雅了,在 TypeScript 中,编写复杂代码的时候,会经常使用泛型。
class SelectGirl {
constructor(private girls: string[] | number[]) {}
getGirl(index: number): string | number {
return this.girls[index];
}
}
初始类的泛型
这时候我们要用泛型重构代码,要如何作那?有了上节课的基础,应该很好理解,就是用<>编写,我们把代码修改成了这个样子。
class SelectGirl<T> {
constructor(private girls: T[]) {}
getGirl(index: number): T {
return this.girls[index];
}
}
const selectGirl = new SelectGirl(["小红", "小丽", "小影"]);
console.log(selectGirl.getGirl(1));
这时候代码并不报错,也使用了泛型,但是在实例化对象的时候,TypeScript 是通过类型推断出来的。上节已经介绍,这种方法并不好,所以还是需要在实例化对象的时候,对泛型的值进行确定,比如是string类型,就这样写。
const selectGirl = new SelectGirl() < string > ["小红", "小丽", "小影"];
这就是类里边最基础的泛型使用了,如果你还不理解,请现在敲出上面的例子进行练习,不要继续学习了。
泛型中的继承
现在需求又变了,要求返回是一个对象中的name,也就是下面的代码要改成这个样子。
return this.girls[index].name;
现在的代码一定是报错的,但是这时候还要求我们这么做,意思就是说传递过来的值必须是一个对象类型的,里边还要有name属性。这时候就要用到继承了,我用接口的方式来实现。写一个Girl的接口,每个接口里都要有 name 属性。代码如下:
interface Girl {
name: string;
}
有了接口后用extends关键字实现泛型继承,代码如下:
class SelectGirl<T extends Girl> {
...
}
这句代码的意思是泛型里必须有一个name属性,因为它继承了Girl接口。
现在程序还是报错的,因为我们getGirl方法的返回类型还不对,这时候应该是一个string类型才对,所以代码应该改为下面的样子:
interface Girl {
name: string;
}
class SelectGirl<T extends Girl> {
constructor(private girls: T[]) {}
getGirl(index: number): string {
return this.girls[index].name;
}
}
const selectGirl = new SelectGirl([
{ name: "小红" },
{ name: "小丽" },
{ name: "小影" },
]);
console.log(selectGirl.getGirl(1));
我们回过头来看一下这段代码的意思,就是我们在SelectGirl类中使用了泛型,意思是我不知道我以后要用什么类型,但是我有一个约束条件,这个类型,必须要有一个name属性。这个在工作中经常使用,所以必须要好好理解这的知识。 初学泛型肯定会很难理解,我当时看书也是看的一脸懵,经过反复的实验和看别人的源代码,才对泛型有了比较深的理解。
泛型约束
现在的泛型可以是任意类型,可以是对象、字符串、布尔、数字都是可以的。但你现在要求这个泛型必须是string或者number类型。我们还是拿上面的例子,不过把代码改为最初的样子。
class SelectGirl<T> {
constructor(private girls: T[]) {}
getGirl(index: number): T {
return this.girls[index];
}
}
const selectGirl = new SelectGirl<string>(["小红", "小丽", "小影"]);
console.log(selectGirl.getGirl(1));
然后进行约束,这时候还是可以使用关键字extends来进行约束,把代码改成下面的样子。
class SelectGirl<T extends number | string> {
//.....
}
作为教学泛型讲这些就可以了,但是在实际工作中,泛型的应用更广泛和复杂,这些需要在实际项目中不断精进和加深理解。
以上关于20. TypeScript 类中泛型(难点)的文章就介绍到这了,更多相关内容请搜索码云笔记以前的文章或继续浏览下面的相关文章,希望大家以后多多支持码云笔记。
如若内容造成侵权/违法违规/事实不符,请将相关资料发送至 admin@mybj123.com 进行投诉反馈,一经查实,立即处理!
重要:如软件存在付费、会员、充值等,均属软件开发者或所属公司行为,与本站无关,网友需自行判断
码云笔记 » 20. TypeScript 类中泛型(难点)
微信
支付宝