在进入模块裁减之前,让咱们看看一些 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);  }}

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"); // baconconsole.log(pet.name = "Looty"); // Lootyconsole.log(pet.age = 3); // 3console.log(pet.walk("park")); // Likes to walk in the park

当初你可能想晓得,与其先申明一个接口,而后在 Pet 原型中增加 walk 办法的实现,为什么咱们不间接申明一个同名的类,这样当类被初始化时,咱们将领有来自两者的办法 课?

答案是,TypeScript 不容许在类之间合并,所以咱们不能创立两个或多个同名的类。