2012-11-18 101 views
13

TypeScripts以“声明式”方式抽取模块导入/导出。TypeScript - 条件模块导入/导出

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

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

TypeScript自带的io.ts在TSC编译器中对输入/输出进行了抽象,手动绕过了内置TypeScript自己的模块语法。这是唯一的方法吗?

P.S.如果语句是TypeScript只允许在顶层的导入语句,只需坚持导入fs =模块(“fs”)的问题。这意味着在WSH 要求(“fs”)将被执行并明显失败,因为要求是未定义的。

回答

8

我同意的事实,他们只能有顶级的范围是次优的最好的。除了你提到的问题外,这也意味着软件的初始加载时间较慢。例如,在nodejs中,我现在有时会在函数中加载模块,如果该函数很少使用。所以我的应用程序启动速度更快,因为它尚未加载该模块。

当然,你可以使用要求或AMD直接,但比你会错过一些打字好处。

我觉得然而,真正的问题在于这样一个事实:和谐/ ES6定义的模块是顶层和TS似乎是下面这一建议。所以不确定没有来自标准组织的TS团队可以做多少事情。

0

有在打字稿动态进口的机制,虽然有所不同实施基于模块的那种。

下面的例子(对于AMD)将有条件地加载模块:

declare function require(moduleNames: string[], onLoad: (...args: any[]) => void): void; 

import * as ModuleAlias from './mod'; 

const someCondition = true; 

if (someCondition) { 
    require(["./mod"], (module: typeof ModuleAlias) => { 
     console.log(module.go()); 
    }); 
} 

在该文件的顶部的import语句是惰性的,并且该模块的实际负荷不会发生,除非条件if (someCondition)是真的。

你可以通过改变someCondition,看到网络选项卡上的影响进行测试,或者你可以看看生成的代码......在动力版本,"./mod"不会出现在define通话。在非动态的一个,它的确如此。

通过动态加载

define(["require", "exports"], function (require, exports) { 
    "use strict"; 
    Object.defineProperty(exports, "__esModule", { value: true }); 
    const someCondition = true; 
    if (someCondition) { 
     require(["./mod"], (module) => { 
      console.log(module.go()); 
     }); 
    } 
}); 

没有动态加载

define(["require", "exports", "./mod"], function (require, exports, ModuleAlias) { 
    "use strict"; 
    Object.defineProperty(exports, "__esModule", { value: true }); 
    const someCondition = true; 
    if (someCondition) { 
     console.log(ModuleAlias.go()); 
    } 
}); 
5

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

有总是发出的出口,但要根据运行时间值的内容有所不同。例如。:

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

然后在消耗文件,导入导出,检查进口值存在,如果确实如此,分配否则你导入单机的所有值设置为一组变量:

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

const { hydrateRecords, fillBlanks, extractHeaders } = priv as any; 
// these will exist if environment var BUILD_MODE==='test' 

限制:

  1. 您可悲的是必须设置的进口“任意”,使编译器高兴。
  2. 您需要检查是否定义了具体的导入(但与该领域一起)。
  3. 导入文件将期望值被定义。因此,您必须确保导入文件实际上需要模块(如果您正在处理仅在测试期间运行的文件,那么这很好),或者您必须为其实际上未导出的情况定义替代值。

尽管如此,它仍然适合我的目的,希望它也适用于您。这对单元测试私有方法特别有用。