這篇文章將概括介紹在TypeScript里使用模塊與命名空間來組織代碼的方法。 我們也會談及命名空間和模塊的高級使用場景,和在使用它們的過程中常見的陷井。
查看模塊章節(jié)了解關(guān)于模塊的更多信息。 查看命名空間章節(jié)了解關(guān)于命名空間的更多信息。
命名空間是位于全局命名空間下的一個普通的帶有名字的JavaScript對象。
這令命名空間十分容易使用。
它們可以在多文件中同時使用,并通過--outFile結(jié)合在一起。
命名空間是幫你組織Web應(yīng)用不錯的方式,你可以把所有依賴都放在HTML頁面的<script>標(biāo)簽里。
但就像其它的全局命名空間污染一樣,它很難去識別組件之間的依賴關(guān)系,尤其是在大型的應(yīng)用中。
像命名空間一樣,模塊可以包含代碼和聲明。 不同的是模塊可以聲明它的依賴。
模塊會把依賴添加到模塊加載器上(例如CommonJs / Require.js)。 對于小型的JS應(yīng)用來說可能沒必要,但是對于大型應(yīng)用,這一點(diǎn)點(diǎn)的花費(fèi)會帶來長久的模塊化和可維護(hù)性上的便利。 模塊也提供了更好的代碼重用,更強(qiáng)的封閉性以及更好的使用工具進(jìn)行優(yōu)化。
對于Node.js應(yīng)用來說,模塊是默認(rèn)并推薦的組織代碼的方式。
從ECMAScript 2015開始,模塊成為了語言內(nèi)置的部分,應(yīng)該會被所有正常的解釋引擎所支持。 因此,對于新項目來說推薦使用模塊做為組織代碼的方式。
這部分我們會描述常見的命名空間和模塊的使用陷井和如何去避免它們。
/// <reference>一個常見的錯誤是使用/// <reference>引用模塊文件,應(yīng)該使用import。
要理解這之間的區(qū)別,我們首先應(yīng)該弄清編譯器是如何根據(jù)import路徑(例如,import x from "...";或import x = require("...")里面的...,等等)來定位模塊的類型信息的。
編譯器首先嘗試去查找相應(yīng)路徑下的.ts,.tsx再或者.d.ts。
如果這些文件都找不到,編譯器會查找外部模塊聲明。
回想一下,它們是在.d.ts文件里聲明的。
myModules.d.ts// In a .d.ts file or .ts file that is not a module:
declare module "SomeModule" {
export function fn(): string;
}
myOtherModule.ts/// <reference path="myModules.d.ts" />
import * as m from "SomeModule";
這里的引用標(biāo)簽指定了外來模塊的位置。
這就是一些Typescript例子中引用node.d.ts的方法。
如果你想把命名空間轉(zhuǎn)換為模塊,它可能會像下面這個文件一件:
shapes.tsexport namespace Shapes {
export class Triangle { /* ... */ }
export class Square { /* ... */ }
}
頂層的模塊Shapes包裹了Triangle和Square。
對于使用它的人來說這是令人迷惑和討厭的:
shapeConsumer.tsimport * as shapes from "./shapes";
let t = new shapes.Shapes.Triangle(); // shapes.Shapes?
TypeScript里模塊的一個特點(diǎn)是不同的模塊永遠(yuǎn)也不會在相同的作用域內(nèi)使用相同的名字。 因為使用模塊的人會為它們命名,所以完全沒有必要把導(dǎo)出的符號包裹在一個命名空間里。
再次重申,不應(yīng)該對模塊使用命名空間,使用命名空間是為了提供邏輯分組和避免命名沖突。 模塊文件本身已經(jīng)是一個邏輯分組,并且它的名字是由導(dǎo)入這個模塊的代碼指定,所以沒有必要為導(dǎo)出的對象增加額外的模塊層。
下面是改進(jìn)的例子:
shapes.tsexport class Triangle { /* ... */ }
export class Square { /* ... */ }
shapeConsumer.tsimport * as shapes from "./shapes";
let t = new shapes.Triangle();
就像每個JS文件對應(yīng)一個模塊一樣,TypeScript里模塊文件與生成的JS文件也是一一對應(yīng)的。
這會產(chǎn)生一個效果,就是無法使用--outFile來讓編譯器合并多個模塊文件為一個JavaScript文件。