TypeScript 裏的 module 概念

Modulesjavascript

JavaScript 在處理模塊化代碼方面有着悠久的歷史。 TypeScript 自 2012 年問世以來,已經實現了對許多這些格式的支持,但隨着時間的推移,社區和 JavaScript 規範已經融合到一種稱爲 ES 模塊(或 ES6 模塊)的格式上。 您可能知道它是 import/export 語法。html

ES Modules 於 2015 年添加到 JavaScript 規範中,到 2020 年在大多數 Web 瀏覽器和 JavaScript 運行時中獲得普遍支持。java

爲了重點,手冊將涵蓋 ES 模塊及其流行的前體 CommonJS module.exports = 語法,您能夠在模塊下的參考部分中找到有關其餘模塊模式的信息。typescript

How JavaScript Modules are Defined

在 TypeScript 中,就像在 ECMAScript 2015 中同樣,任何包含頂級導入或導出的文件都被視爲一個模塊。瀏覽器

相反,沒有任何頂級導入或導出聲明的文件被視爲腳本,其內容在全局範圍內可用(所以也對模塊可用)。app

模塊在它們本身的範圍內執行,而不是在全局範圍內。 這意味着在模塊中聲明的變量、函數、類等在模塊外部不可見,除非它們使用導出形式之一顯式導出。 相反,要使用從不一樣模塊導出的變量、函數、類、接口等,必須使用其中一種導入形式導入。dom

非模塊

在咱們開始以前,瞭解 TypeScript 將什麼視爲模塊很重要。 JavaScript 規範聲明任何沒有導出或頂級 await 的 JavaScript 文件都應被視爲腳本而不是模塊。模塊化

在腳本文件中,變量和類型被聲明爲在共享全局範圍內,而且假設您將使用 --outFile 編譯器選項將多個輸入文件鏈接到一個輸出文件中,或者在其中使用多個
\<script> 標記 您的 HTML 以加載這些文件(以正確的順序!)。函數

若是您有一個當前沒有任何導入或導出的文件,但您但願被視爲一個模塊,請添加如下行:ui

export {};

這會將文件更改成不導出任何內容的模塊。 不管您的模塊目標如何,此語法都有效。

ES Module 語法

文件能夠經過 export default 聲明主導出:

// @filename: hello.ts
export default function helloWorld() {
  console.log("Hello, world!");
}

This is then imported via:

import hello from "./hello.js";
hello();

除了默認導出以外,您還能夠經過省略默認導出來導出多個變量和函數:

// @filename: maths.ts
export var pi = 3.14;
export let squareTwo = 1.41;
export const phi = 1.61;

export class RandomNumberGenerator {}

export function absolute(num: number) {
  if (num < 0) return num * -1;
  return num;
}

在另外一個文件裏用大括號導入:

import { pi, phi, absolute } from "./maths.js";

console.log(pi);
const absPhi = absolute(phi);

還能夠用 import alias 語法:

import { pi as π } from "./maths.js";

console.log(π);

您能夠將全部導出的對象放入一個使用 * 做爲名稱的命名空間中:

// @filename: app.ts
import * as math from "./maths.js";

console.log(math.pi);
const positivePhi = math.absolute(math.phi);

直接 import 一個文件會有什麼後果?

// @filename: app.ts
import "./maths.js";

console.log("3.14");

在這種狀況下,導入什麼都不作。 可是,對 maths.ts 中的全部代碼都進行了評估,這可能會觸發影響其餘對象的反作用。

TypeScript 加強了 import 語法,能夠只 import module 裏的 type 定義。

// @filename: animal.ts
export type Cat = { breed: string; yearOfBirth: number };
'createCatName' cannot be used as a value because it was imported using 'import type'.
export type Dog = { breeds: string[]; yearOfBirth: number };
export const createCatName = () => "fluffy";

// @filename: valid.ts
import type { Cat, Dog } from "./animal.js";
export type Animals = Cat | Dog;

// @filename: app.ts
import type { createCatName } from "./animal.js";
const name = createCatName();

TypeScript’s Module Resolution Options

模塊解析是從 import 或 require 語句中獲取字符串並肯定該字符串引用哪一個文件的過程。

TypeScript 包括兩種解析策略:Classic 和 Node。 經典,當編譯器標誌模塊不是 commonjs 時的默認值,包含在內是爲了向後兼容。 Node 策略複製了 Node.js 在 CommonJS 模式下的工做方式,並額外檢查了 .ts 和 .d.ts。

有許多 TSConfig 標誌會影響 TypeScript 中的模塊策略:moduleResolution、baseUrl、paths、rootDirs。

有關這些策略如何工做的完整詳細信息,您能夠查閱模塊解決方案。

TypeScript’s Module Output Options

有兩個選項會影響發出的 JavaScript 輸出:

  • target 肯定哪些 JS 功能被降級(轉換爲在較舊的 JavaScript 運行時中運行)以及哪些保持不變
  • module:肯定模塊之間使用哪些代碼進行交互的模塊

您使用的目標取決於您但願在其中運行 TypeScript 代碼的 JavaScript 運行時中可用的功能。這多是:您支持的最舊的 Web 瀏覽器,您但願運行或可能來自的最低版本的 Node.js 來自您的運行時的獨特約束——例如 Electron。

模塊之間的全部通訊都經過模塊加載器進行,編譯器標誌模塊肯定使用哪個。在運行時,模塊加載器負責在執行以前定位並執行模塊的全部依賴項。

例如,這是一個使用 ES 模塊語法的 TypeScript 文件,展現了模塊的幾個不一樣選項。

下面是 TypeScript 原始文件:

import { valueOfPi } from "./constants.js";

export const twoPi = valueOfPi * 2;

下面是 ES2020 output:

import { valueOfPi } from "./constants.js";
export const twoPi = valueOfPi * 2;

下面是 CommonJS:

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.twoPi = void 0;
const constants_js_1 = require("./constants.js");
exports.twoPi = constants_js_1.valueOfPi * 2;

下面是 UMD:

(function (factory) {
    if (typeof module === "object" && typeof module.exports === "object") {
        var v = factory(require, exports);
        if (v !== undefined) module.exports = v;
    }
    else if (typeof define === "function" && define.amd) {
        define(["require", "exports", "./constants.js"], factory);
    }
})(function (require, exports) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    exports.twoPi = void 0;
    const constants_js_1 = require("./constants.js");
    exports.twoPi = constants_js_1.valueOfPi * 2;
});
相關文章
相關標籤/搜索