TypeScript基礎入門之宣告合併(三)
宣告合併
將名稱空間與類,函式和列舉合併
名稱空間足夠靈活,也可以與其他型別的宣告合併。
為此,名稱空間宣告必須遵循它將與之合併的宣告。
生成的宣告具有兩種宣告型別的屬性。
TypeScript使用此功能來模擬JavaScript以及其他程式語言中的某些模式。
將名稱空間與類合併
這為使用者提供了一種描述內部類的方法。
class Album { label: Album.AlbumLabel; } namespace Album { export class AlbumLabel { } }
合併成員的可見性規則與"合併名稱空間"部分中描述的相同,因此我們必須匯出合併類的AlbumLabel類才能看到它。
最終結果是在另一個類內部管理的類。
您還可以使用名稱空間向現有類新增更多靜態成員。
除了內部類的模式之外,您還可能熟悉建立函式的JavaScript實踐,然後通過向函式新增屬性來進一步擴充套件函式。
TypeScript使用宣告合併以型別安全的方式構建這樣的定義。
function buildLabel(name: string): string { return buildLabel.prefix + name + buildLabel.suffix; } namespace buildLabel { export let suffix = ""; export let prefix = "Hello, "; } console.log(buildLabel("Sam Smith"));
同樣,名稱空間可用於擴充套件具有靜態成員的列舉:
enum Color { red = 1, green = 2, blue = 4 } namespace Color { export function mixColor(colorName: string) { if (colorName == "yellow") { return Color.red + Color.green; } else if (colorName == "white") { return Color.red + Color.green + Color.blue; } else if (colorName == "magenta") { return Color.red + Color.blue; } else if (colorName == "cyan") { return Color.green + Color.blue; } } }
不允許合併
並非TypeScript中允許所有合併。
目前,類不能與其他類或變數合併。
有關模擬類合併的資訊,請參閱TypeScript中的Mixins部分。
模組擴充套件
雖然JavaScript模組不支援合併,但您可以通過匯入然後更新它們來修補現有物件。
讓我們看一下玩具Observable示例:
// observable.js export class Observable<T> { // ... implementation left as an exercise for the reader ... } // map.js import { Observable } from "./observable"; Observable.prototype.map = function (f) { // ... another exercise for the reader }
這在TypeScript中也可以正常工作,但編譯器不瞭解Observable.prototype.map。
您可以使用模組擴充來告訴編譯器:
// observable.ts stays the same // map.ts import { Observable } from "./observable"; declare module "./observable" { interface Observable<T> { map<U>(f: (x: T) => U): Observable<U>; } } Observable.prototype.map = function (f) { // ... another exercise for the reader } // consumer.ts import { Observable } from "./observable"; import "./map"; let o: Observable<number>; o.map(x => x.toFixed());
模組名稱的解析方式與匯入/匯出中的模組說明符相同。
有關更多資訊,請參閱模組
然後合併擴充中的宣告,就好像它們在與原始檔案相同的檔案中宣告一樣。
但是,您無法在擴充中宣告新的頂級宣告 - 只是現有宣告的補丁。
全域性擴充套件您還可以從模組內部向全域性範圍新增宣告:
// observable.ts export class Observable<T> { // ... still no implementation ... } declare global { interface Array<T> { toObservable(): Observable<T>; } } Array.prototype.toObservable = function () { // ... }
全域性擴充套件與模組擴充套件具有相同的行為和限制。