在使用--outFile进行编译时,如何强制Typescript编译器发出定义调用?

时间:2018-06-21 03:24:28

标签: typescript

我需要TypeScript编译器发出的所有.js文件都包括对define函数的AMD样式的调用。看来这应该是TypeScript可以做的一件事,但是我不知道如何一直使用它。

现在,只要.ts文件具有依赖项(import / require)或产生依赖项(export),发出的Javascript将包含AMD define调用。但是,对于我的项目,有效的脚本文件可能既不具有依赖项也不产生依赖关系。

缺少的define调用是一个问题,因为我使用了--outFile编译器开关来生成一个包含所有AMD模块的单个javascript文件,并且该文件/模块立即执行,而无需等待与该级别的其他AMD模块一样,可能在require语句中使用。

示例如下:

module_a.ts 愚蠢,但说明性的破坏性内容(如果意外运行)

const el = document.getElementById("app");
el.innerHTML = "";

在与TypeScript 2.9.2兼容时,使用以下开关:tsc --target es5 --module amd --outFile application.js module_a.ts会产生以下结果:

application.js

var el = document.getElementById("app");
el.innerHTML = "";

但是,此版本的 module_a.ts 将呈现我要查找的内容:

module_a.ts

export const el = document.getElementById("app");
el.innerHTML = "";

application.js 无论我是否使用import / require / export

define("module_a", ["require", "exports"], function (require, exports) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    exports.el = document.getElementById("app");
    exports.el.innerHTML = "";
});

如果找不到强制编译器发出定义的方法,那么我会回来(有一个新问题)找出我的下一个任务,以编写TSLint规则来检测这种情况,以便我知道我需要在TS模块中添加伪造的export

1 个答案:

答案 0 :(得分:0)

The documentation说,在顶层拥有importexport是编译器确定文件是模块还是全局脚本的一部分的唯一方法:

  

在TypeScript中,就像在ECMAScript 2015中一样,任何包含   顶级导入或导出被视为模块。相反,一个文件   没有任何顶级进出口声明的情况将被视为   脚本的内容在全局范围内可用(因此   以及模块)。

正如您在问题中提到的,define仅在编译文件是模块时才出现在输出中。

因此,添加伪造的顶级exportimport是唯一的解决方案。做到这一点的方法在运行时没有任何影响(实际上没有从AMD模块导入或导出任何内容)是导入在其他模块中定义的某种类型:

import {SomeType} from './some-module';

如果在运行时从未使用过SomeType,则编译器将不会在JavaScript中发出importrequire,但仍会将文件编译为模块并添加define功能。

如果您的targetmodule选项为ESNext,则有一种更新且可以说是更好的方法来获得相同的结果-只需在某处添加此语句即可将文件转换为模块:

import.meta;

我认为没有tslint规则要求每个文件都必须是一个模块。我不知道要实现这样的规则有多难-如果tslint规则可以轻松访问TypeScript AST,那么如果它是一个模块,则该规则可以检查SourceFile的{​​{3}}:

    /**
     * The first "most obvious" node that makes a file an external module.
     * This is intended to be the first top-level import/export,
     * but could be arbitrarily nested (e.g. `import.meta`).
     */
    /* @internal */ externalModuleIndicator: Node;