乐趣区

关于typescript:TypeScript-里的-module-概念

Modules

JavaScript 在解决模块化代码方面有着悠久的历史。TypeScript 自 2012 年问世以来,曾经实现了对许多这些格局的反对,但随着工夫的推移,社区和 JavaScript 标准曾经交融到一种称为 ES 模块(或 ES6 模块)的格局上。您可能晓得它是 import/export 语法。

ES Modules 于 2015 年增加到 JavaScript 标准中,到 2020 年在大多数 Web 浏览器和 JavaScript 运行时中失去广泛支持。

为了重点,手册将涵盖 ES 模块及其风行的前体 CommonJS module.exports = 语法,您能够在模块下的参考局部中找到无关其余模块模式的信息。

How JavaScript Modules are Defined

在 TypeScript 中,就像在 ECMAScript 2015 中一样,任何蕴含顶级导入或导出的文件都被视为一个模块。

相同,没有任何顶级导入或导出申明的文件被视为脚本,其内容在全局范畴内可用(因而也对模块可用)。

模块在它们本人的范畴内执行,而不是在全局范畴内。这意味着在模块中申明的变量、函数、类等在模块内部不可见,除非它们应用导出模式之一显式导出。相同,要应用从不同模块导出的变量、函数、类、接口等,必须应用其中一种导入模式导入。

非模块

在咱们开始之前,理解 TypeScript 将什么视为模块很重要。JavaScript 标准申明任何没有导出或顶级 await 的 JavaScript 文件都应被视为脚本而不是模块。

在脚本文件中,变量和类型被申明为在共享全局范畴内,并且假如您将应用 –outFile 编译器选项将多个输出文件连贯到一个输入文件中,或者在其中应用多个
\<script> 标记 您的 HTML 以加载这些文件(以正确的程序!)。

如果您有一个以后没有任何导入或导出的文件,但您心愿被视为一个模块,请增加以下行:

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;
});
退出移动版