TypeScript - 条件模块导入/导出

Ole*_*lik 18 typescript

TypeScripts以"声明"方式抽象出模块导入/导出.

但是,如果我想根据某些运行时计算条件导入或导出某些内容呢?

最常见的用例是在Node.js和Windows Script Host等平台之间共享代码.

TypeScript自己的io.ts在TSC编译器中抽象输入/输出,手动破解内置的TypeScript自己的模块语法.这是唯一的方法吗?

PS将import fs = module("fs")粘贴到if语句中的问题是TypeScript只允许顶层的import语句.这意味着在WSH中需要执行("fs")并且显然会失败,因为需要是未定义的.

mPr*_*inC 22

TypeScript v2.4 开始,您可以使用动态导入来实现条件导入

一个异步示例:

async function importModule(moduleName):Promise<any>{
    console.log("importing ", moduleName);
    const importedModule = await import(moduleName);
    console.log("\timported ...");
    return importedModule;
}

let moduleName:string = "module-a";
let importedModule = await importModule(moduleName);
console.log("importedModule", importedModule);
Run Code Online (Sandbox Code Playgroud)


And*_*ner 9

我有一个稍微笨重但非常有效的解决方案,特别是如果你使用条件导入/导出进行单元测试.

具有始终发出的导出,但使内容根据运行时值而变化.例如:

// outputModule.ts
export const priv = (process.env.BUILD_MODE === 'test')
  ? { hydrateRecords, fillBlanks, extractHeaders }
  : null
Run Code Online (Sandbox Code Playgroud)

然后在使用文件中,导入导出,检查导入的值是否存在,如果存在,则将您以其他方式单独导入的所有值分配给一组变量:

// importingModule.spec.ts
import { priv } from './outputModule';

const { hydrateRecords, fillBlanks, extractHeaders } = priv as any;
// these will exist if environment var BUILD_MODE==='test'
Run Code Online (Sandbox Code Playgroud)

限制:

  1. 你不幸的是必须将导入设置为'any'以使编译器满意.
  2. 您需要检查是否定义了特定的导入(但是该区域附带了).
  3. 导入文件将期望定义值.因此,您必须确保导入文件实际上需要模块(如果您仅处理仅在测试期间运行的文件,那就没问题),或者您必须为实际未实际导出的情况定义替代值.

尽管如此,它对我来说非常有用,我希望它对你也有用.它对单元测试私有方法特别有用.


小智 8

我同意他们只能达到范围的事实最多是次优的.除了你说的问题,它还意味着软件的初始加载时间较慢.例如,在nodejs中,如果很少使用该函数,我现在有时会在函数中加载模块.所以我的应用程序启动得更快,因为它还没有加载该模块.

当然你可以直接使用require或AMD,但是你会错过一些输入的好处.

然而,我认为真正的问题在于和谐/ es6定义的模块是顶层的,TS似乎遵循该提议.所以不确定TS团队在没有标准组织的情况下可以做多少.