什么是 TypeScript 的 Module Augmentation

举报
汪子熙 发表于 2022/09/12 11:20:38 2022/09/12
【摘要】 在进入模块扩充之前,让我们看看一些 TypeScript 合并原则,这些原则将随着我们的进步而变得有用。TypeScript 支持创建完全同名的 class 和 interface:class Food { cheese: string;}interface Food { bacon: string;}const food = new Food();food.bacon = "nice...

在进入模块扩充之前,让我们看看一些 TypeScript 合并原则,这些原则将随着我们的进步而变得有用。

TypeScript 支持创建完全同名的 class 和 interface:

class Food {
  cheese: string;
}

interface Food {
  bacon: string;
}

const food  = new Food();
food.bacon = "nice bacon";
food.cheese = "sweet cheese";

console.log(food); // {bacon: "nice bacon", cheese: "sweet cheese"}

在我们上面的例子中,我们可以看到,即使在 Food 类中只声明了 cheese,食物变量也包含 bacon 和 cheese。 这是因为,接口与类合并了。

但如果 interface 里包含的是方法,结果又如何?

class Food {
  cheese: string;
}

interface Food {
  bacon: string;
  bake(item: string);
}

const food  = new Food();

food.bake("cake"); // Error: food.bake is not a function

但是,bake 方法会在intelliSense 的帮助下显示在food 变量上,因为Food 类和接口Food 将合并,调用bake 方法会导致错误,因为接口只包含声明而不包含实现。 为了解决这个问题,我们可以将bake的实现添加到Food原型中。

Food.prototype.bake = (item) => console.log(item);

之后 bake 方法调用就能够工作了:

food.bake("cake"); // cake

模块扩充帮助我们将功能扩展到我们可能无法访问的第三方库或其他文件中的类

假设我们有一个带有 name 属性和 feed 方法的 Pet 类。

export class Pet {
  name: string;

  feed(feedType: string) {
    console.log(feedType);
  }
}

然后我们决定将这个类导入到我们的 index.ts 文件中,但不是只使用 Pet 类中的方法和属性,我们想要添加更多功能。 我们可以使用模块扩充来做到这一点。

首先,我们将 Pet 类导入到 index.ts 文件中。

import { Pet } from "./pet";

./pet 是一个模块。 为了扩展它,我们声明了一个使用相同名称的模块,在该模块中,我们将声明一个与我们尝试扩展的类同名的接口。 在接口中,我们将包含要添加到扩展类的属性和方法。

declare module "./pet" {
  interface Pet {
    age: number;
    walk(location: string);
  }
}

给 Pet 增添了一个 walk 方法的定义

TypeScript 将合并 Pet 类和 Pet 接口,因为它们可以在同一个 ./pet 模块中找到。

但这还不是全部。 记住我解释过,接口不包含方法的实现,而只包含它们的声明。 为此,我们将在 Pet 的原型中添加 walk 方法的实现。

Pet.prototype.walk = (location:string) => `Likes to walk in the ${location}`

现在我们可以调用 Pet 类中的方法和属性以及新声明的 Pet 接口。

const pet = new Pet();

pet.name = "Looty";
pet.age = 3;

pet.feed("bacon"); // bacon
console.log(pet.name = "Looty"); // Looty
console.log(pet.age = 3); // 3
console.log(pet.walk("park")); // Likes to walk in the park

现在你可能想知道,与其先通过 declare module 在增强后的 module 里声明一个接口,然后在 Pet 原型中添加 walk 方法的实现,为什么我们不直接声明一个同名的类,这样当类被初始化时,我们将拥有来自两者的方法?

答案是:TypeScript 不允许在类之间合并,所以我们不能创建两个或多个同名的类。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。