【问题标题】:Type-safely import TypeScript modules from paths known only at run-time类型安全地从仅在运行时知道的路径导入 TypeScript 模块
【发布时间】:2020-10-07 20:56:21
【问题描述】:

假设我有一个 TypeScript 代码和资产的文件树,我从某个任意 URL(例如 CDN 和调试位置之间)提供服务 - 我希望能够导入该模块的根目录,并允许树的其余部分在需要时正确导入(即无需多次提供加载路径)。

在 JavaScript 中,我可能会这样做:

export class MyModule {
    private dependentModulePromise;

    constructor(rootpath) {
        this.dependentModulePromise = import(rootpath + '/dependentModule');
    }
}

但是,如果我要在 TypeScript 中执行此操作,我希望它尽可能地是类型安全的。显然,我需要在此处使用类型断言来导入原始动态字符串,但是如何安全地告诉 TypeScript 我正在加载的类型,而不会遇到名称冲突或同步导入模块(在 Webpack 之类的东西中) ,使其成为捆绑包的一部分)?

我确实尝试过这个扩展:

import * as DependentModule from '/dependentModule';

export class MyModule {
    private dependentModulePromise: Promise<DependentModule>;

    constructor(rootpath) {
        this.dependentModulePromise = import(rootpath + '/dependentModule') as Promise<DependentModule>;
    }
}

但我最终得到一个错误,告诉我命名空间 DependentModule 不能用作类型。

【问题讨论】:

  • 问题出在import *。当您从文件中导入所有内容并将其分配给 DependentModule 之类的名称时,typescript 会将其视为命名空间,并将单个导出视为该命名空间上的值。 /dependentModule 有默认导出吗?
  • @LindaPaiste 它必须有一个吗?如果是这样,我可以做到这一点,但如果可以的话,我更希望能够导入任意模块。
  • 说实话,我不知道这是否真的能解决你的问题。我只知道import *是当前错误的来源。

标签: typescript


【解决方案1】:

这是非常接近的:如果/dependentModule 有一个默认导出,而不是尝试导出命名空间,那么它可以正常工作。

// Here, dependentModule exports a class
import { default as DependentModule_TYPE_ONLY } from '/dependentModule';

export class MyModule {
    private dependentModulePromise: Promise<new () => DependentModule_TYPE_ONLY>;

    constructor(rootpath) {
        this.dependentModulePromise = import(rootpath + '/dependentModule') as Promise<new () => DependentModule>;
    }
    
    public async doStuffWithDependentModule() {
        const DependentModule = await this.dependentModulePromise;
        const m = new DependentModule();
        // now do typesafe stuff with m
    }

}

显然,最好的方法是,如果此默认导出实现了在其他地方找到的某个接口或类型形状,那么可以将 promise 强制转换为该接口或类型,而不是作为类的实例(即,如果 DependentModule 实现 IInterfaceOfInterest,那么import 承诺的类型是Promise&lt;new () =&gt; IInterfaceOfInterest&gt;)。

【讨论】:

    猜你喜欢
    • 2017-06-26
    • 2014-11-14
    • 2012-10-14
    • 2020-12-10
    • 2019-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多