美文网首页
TypeScript 里的 module 概念

TypeScript 里的 module 概念

作者: _扫地僧_ | 来源:发表于2021-08-13 10:47 被阅读0次

    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;
    });
    

    相关文章

      网友评论

          本文标题:TypeScript 里的 module 概念

          本文链接:https://www.haomeiwen.com/subject/fjqkultx.html