如何在 TypeScript 中使用命名空間

如何在 TypeScript 中使用命名空間

當兩個或多個代碼組件對變量、函數或類使用相同的名稱時,就會發生命名衝突。它們在許多人在同一代碼庫上工作的大型項目中很常見。它們會使確定哪個代碼組件導致錯誤變得困難。

使用命名空間,您可以組織和管理您的代碼,以便相關組件組位於一個公共標識符下。這將減輕命名衝突的風險。

創建命名空間

您可以使用namespace關鍵字在 TypeScript 中創建命名空間。在它後面跟一個標識符來命名命名空間和一個用花括號括起來的塊。語法類似於您在 JavaScript 中創建類所使用的語法。

例如:

namespace Example {}

然後,您可以在命名空間塊中聲明命名空間的成員——變量、函數和類:

namespace Example {
  export function Foo(): void {
    console.log("This is a function inside the Example namespace");
  }

  export class Bar {
    property: string;

    constructor(property: string) {
      this.property = property;
    }
  }

  export const baz = "This is a namespace variable"
}

在上面的示例中,FooBarbazExample命名空間的成員。默認情況下,您只能訪問同一命名空間內的命名空間成員。使用export關鍵字使名稱空間的每個成員都可以在其外部訪問。

您可以通過使用點表示法調用命名空間的成員名稱來訪問命名空間的所有公開可用成員:

Example.foo(); // This is a function inside the Example namespace

const bar = new Example.Bar("string");
console.log(bar.property); // string


console.log(Example.baz); // This is a namespace variable

嵌套命名空間

TypeScript 允許您將命名空間嵌套在其他命名空間中,從而為您的代碼創建層次結構。嵌套命名空間可以通過將相關命名空間分組在一個公共標識符下來進一步降低命名衝突的風險。

例如:

namespace Example {
  export const property_1 = "Foo";

  export namespace Bar {
    export const printFoo = function () {
      console.log(property_1);
    };
  }

  export namespace Baz {
    export class Foo {
      property: string;

      constructor(property: string) {
        this.property = property;
      }
    }
  }
}

上面的代碼塊提供了一個嵌套命名空間的示例。Example命名空間是頂級命名空間,包含Bar命名空間和Baz命名空間。

您可以使用遵循您創建的層次結構的點表示法訪問嵌套命名空間中的屬性。

例如:

console.log(Example.property_1); // Foo
Example.Bar.printFoo() // Foo
const foo = new Example.Baz.Foo("example")

此示例代碼通過父命名空間訪問命名空間的每個成員。直接訪問一個屬性,而不是通過它的父命名空間,會拋出一個錯誤:

Example.printFoo()
// error TS2339: Property 'printFoo' does not exist on type 'typeof Example'

雖然嵌套命名空間可以幫助您組織代碼,但深度嵌套的命名空間可能會產生相反的效果。深度嵌套的命名空間使您的代碼更難閱讀和維護。

命名空間別名

命名空間別名是命名空間成員的簡稱,它更易於引用。

您可以使用import關鍵字後跟要分配給別名的名稱來創建名稱空間別名。然後,將import關鍵字和別名分配給命名空間成員。

例如:

namespace Car {
  export namespace Tesla {
    export class ModelX {
      create(): String {
        return `Model X Created`
      }
    }
  }

  export namespace Toyota {
     export class Camry {}
  }

  export namespace Ford {
    export class Mustang {}
  }
}

// Creating the alias
import tesla = Car.Tesla

const modelX = new tesla.ModelX()
modelX.create() // Model X Created

此示例為Car.Tesla命名空間創建一個別名。您可以使用此別名更輕鬆地訪問Tesla命名空間的屬性,例如 ModelX 類。

在多個文件中使用命名空間

要在不同的文件中使用命名空間,您必須導入它。導入命名空間不同於導入變量、函數、類等。根據項目的模塊系統,您可以使用requireimport關鍵字導入它們。

但是,您只能使用三重斜杠指令導入名稱空間,該指令是包含 XML 標記的單行註釋。

例如:

// main.ts

/// <reference path="index.ts"/>
Example.foo()

此示例在main.ts文件中使用三重斜杠指令。該指令引用包含Example命名空間的index.ts文件。如果不導入,名稱空間僅在定義它的同一個文件中可用。

引用index.ts文件後,您可以訪問Example命名空間及其公開可用的成員。例如,您可以在Example命名空間上調用foo方法。

使用多個文件後,您需要確保 TypeScript 編譯並加載所有必要的代碼。您可以通過使用outFile選項連接 TypeScript 編譯器的輸出來實現。然後,這會將所有輸入文件編譯成一個 JavaScript 輸出文件。像這樣運行編譯器的一般語法是:

tsc --outFile <JAVASCRIPT_FILE> <TYPESCRIPT_FILE>

<JAVASCRIPT_FILE>替換為目標 JavaScript 文件的名稱。將<TYPESCRIPT_FILE>替換為包含三斜杠指令的 TypeScript 文件的名稱。

例如:

tsc --outFile index.js main.ts

此命令會將main.ts文件的內容以及三重斜杠指令引用的所有文件編譯到index.js文件中。

或者,您可以單獨指定每個文件:

tsc --outFile <JAVASCRIPT_FILE> <TYPESCRIPT_FILE_1> <TYPESCRIPT_FILE_2>

重要的是要注意三重斜杠指令僅在文件頂部聲明時有效。如果您嘗試在其他任何地方使用它,TypeScript 會將其視為沒有特殊含義的常規單行註釋。

你應該使用命名空間還是模塊?

雖然命名空間並未被棄用,但通常建議使用 ES6 模塊組織和管理您的代碼。模塊更易於維護和管理,您可以將它們限定在多個文件中。

此外,您可以根據文件級別的導入和導出來指定模塊之間的關係。命名空間不能定義它們的依賴關係。

最終,命名空間和模塊之間的選擇將取決於項目的特定需求和要求,因為兩者都提供了一種在 TypeScript 中組織和管理代碼的有價值的方式。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *