网站搜索

在 TypeScript 中使用静态类型动态加载模块的正确方法


我正在使用 TypeScript 和 WebPack。

有一个模块我需要动态加载。当前的解决方案是:

declare function require(module: string): any;

const m = require("./something");
m.f();

但这样我相比之下失去了静态类型:

import {f} from "./something";

有没有办法用我的模块类型来为动态加载的模块进行类型定义?

答案#1

我认为你想要使用的是

    import * as something from './something'
    something.fn()

否则请详细说明你的问题。

在 TypeScript 中有几种类型的导入

    import {something} from './something' //represents a named class or function
    something from './something' //represents a default export from a module
    import * as something from './something' // is equivalent to let method=require("something")

请在此查看完整参考:https://www.typescriptlang.org/docs/handbook/module-resolution.html

更新

编译器检测每个模块是否在生成的 JavaScript 中被使用。如果一个模块标识符仅作为类型注解的一部分使用,而从未作为表达式使用,那么该模块将不会生成任何 require 调用。未使用引用的这种省略是一种良好的性能优化,同时也允许这些模块的可选加载。

根据文档,这可以由 systemjs、requirejs 和 node 不同地处理。

//node
If(...){let a=require('something')}
//system
If(...){require(['something'],(a))=>{...}}

答案#2

我有一个部分解决方案:

import * as Something from "something"; //this will give you access to type

if(..) {
  let a: typeof Something = require("something")
}

然而,这里有一个问题,如果“something”模块有暴露的接口或类型,它们将不会作为“typeof Something”的一部分显示出来。所以如果有人能帮忙解决这个问题,那就太好了!