typescript 动态导入默认返回 promise,类型丢失;可通过 typeof import() 获取精确模块类型、unpacked 解包 promise、defaultexport 提取默认导出、satisfies 防止路径拓宽,实现接近完美的类型支持。

TypeScript 对动态导入(import())的类型推导本身是有限的——默认情况下,import('xxx') 返回的是 Promise<any></any>,类型信息完全丢失。但通过组合使用类型断言、typeof import()、条件类型和辅助工具类型,可以实现“接近完美”的类型支持。
用 typeof import() 获取模块精确类型
这是最直接、最常用的方式:动态导入后,立即用类型断言把返回值约束为模块的静态类型。
例如导入一个组件库:
const loadWidget = async () => {<br> const widget = await import('widget-lib') as typeof import('widget-lib');<br> return new widget.WidgetComponent();<br>};
这里 typeof import('widget-lib') 不是运行时语法,而是 TypeScript 的类型查询操作符,它能完整提取模块的导出类型(包括命名导出、默认导出、类型定义),比写 any 或手动声明接口更安全、更自动。
用 Unpacked 提取 Promise 解包后的类型
上面例子中 widget 是 Promise<typeof import></typeof>,而你真正需要的是模块对象本身(非 Promise)。可以用条件类型自动解包:
type Unpacked<t> = T extends Promise<infer u> ? U : T;<br>type WidgetModule = Unpacked<returntype loadwidget>>;</returntype></infer></t>
这样 WidgetModule 就是 typeof import('widget-lib') 类型,可直接用于类型提示、参数约束或泛型推导。
处理默认导出与命名导出混合场景
有些模块同时有 export default 和 export const X。此时 typeof import(...) 会生成一个含 default 属性的对象类型。若想直接拿到默认导出类型,可进一步提取:
type DefaultExport<t> = T extends { default: infer D } ? D : T;<br>type WidgetClass = DefaultExport<typeof import>; // 得到 WidgetComponent 构造函数类型</typeof></t>
这样就能安全调用 new WidgetClass(),且 IDE 能补全方法、检查参数。
配合 satisfies 避免类型拓宽(TS 4.9+)
如果模块路径是变量或配置驱动的,直接写 import(path) 可能导致字面量字符串被拓宽为 string,进而让 typeof import() 失效。这时可用 satisfies 锁定路径类型:
const modulePath = 'widget-lib' satisfies string;<br>const mod = await import(modulePath) as typeof import('widget-lib');
或者更稳妥地,用模板字面量类型 + satisfies 约束合法路径集合,防止传入非法字符串。











