在进入模块扩展之前,让我们看看一些TypeScript合并原理,这些原理将随着我们的进步而变得有用。
在 这篇文章中,我们谈到了与接口合并接口,此外,我们还可以将接口与类合并。
1class Food {
2 cheese: string;
3}
4
5interface Food {
6 bacon: string;
7}
8
9const food = new Food();
10food.bacon = "nice bacon";
11food.cheese = "sweet cheese";
12
13console.log(food); // {bacon: "nice bacon", cheese: "sweet cheese"}
在上面的例子中,我们可以看到,食品
变量包含面包
和奶酪
,尽管只有奶酪
在食品
类中被声明。
但是如果我们的界面包含一种方法,例如烤
怎么办?
1class Food {
2 cheese: string;
3}
4
5interface Food {
6 bacon: string;
7 bake(item: string);
8}
9
10const food = new Food();
11
12food.bake("cake"); // Error: food.bake is not a function
尽管如此,在intelliSense的帮助下,在食品
变量上将显示烘焙
方法,因为 类食品
和 界面食品
将合并,称为烘焙
方法会导致错误,因为界面只包含声明,而不是实现。
1Food.prototype.bake = (item) => console.log(item);
现在称之为烘焙
方法将起作用。
1food.bake("cake"); // cake
输入模块增加
**模块扩展帮助我们将功能扩展到我们可能无法访问的第三方库或其他文件中的类。
假设我们有一个宠物
类,具有名称
属性和饲料
方法。
1[label pet.ts]
2export class Pet {
3 name: string;
4
5 feed(feedType: string) {
6 console.log(feedType);
7 }
8}
然后我们决定将这个类导入到我们的 index.ts 文件中,而不是只使用Pet
类中的方法和属性,我们想要添加更多的功能。
首先,我们将我们的宠物
类导入到我们的index.ts
文件中。
1[label index.ts]
2import { Pet } from "./pet";
./pet
是一个模块.为了扩展它,我们有一个使用相同名称的模块声明,在该模块中,我们将声明与我们试图扩展的类相同的名称的界面。
1[label index.ts]
2declare module "./pet" {
3 interface Pet {
4 age: number;
5 walk(location: string);
6 }
7}
TypeScript 将合并宠物
**类和宠物
**界面,因为它们可以在同一个./pet
模块中找到。
请记住,我解释说,界面不包含方法的实现,而只是它们的声明,因此,我们将将步行
方法的实现添加到宠物
的原型
。
1Pet.prototype.walk = (location:string) => `Likes to walk in the ${location}`
现在我们可以调用在宠物
类和新宣布的宠物
界面中发现的方法和属性。
1[label index.ts]
2const pet = new Pet();
3
4pet.name = "Looty";
5pet.age = 3;
6
7pet.feed("bacon"); // bacon
8console.log(pet.name = "Looty"); // Looty
9console.log(pet.age = 3); // 3
10console.log(pet.walk("park")); // Likes to walk in the park
现在你可能想知道,而不是宣布一个界面,然后将步行
方法的实施添加到宠物
原型中,为什么我们不只是声明一个同名类,以便当类被初始化时,我们将有来自两个类的方法?
答案是,TypeScript不允许类之间的合并,所以我们不能创建两个或多个类同名。
希望有用!希望有用!