为何TypeScript无法通过导出名推断模块导出项的类型?
为什么TypeScript无法正确推断懒加载模块导出项的类型?
需求场景
我希望懒加载部分模块的导出项,并对加载后的模块执行一些副作用。
示例代码
目标模块 myModule.ts
// myModule.ts export const message = `hello`; export const date = new Date();
懒加载工具函数 lazy.ts(初始版本)
// lazy.ts export const lazy = async<ModuleShape>( path: string, exportName: keyof ModuleShape, ) => { const module = await import(path) as ModuleShape; // 在这里执行副作用... return module[exportName]; };
使用示例 main.ts
// main.ts import { lazy } from './lazy.ts'; import type * as myModule from './myModule.ts'; const lazyMessage = await lazy<typeof myModule>('./myModule.ts', 'message'); console.log(lazyMessage);
问题描述
这里的问题是:lazyMessage 的类型被推断为联合类型 "hello" | Date,但明明指定了导出名称为 message,预期类型应该是具体的 "hello"。
对比:普通对象的类型推断
如果是普通对象,TypeScript 能正确推断指定属性的类型:
export const myModule = { date: new Date(), message: `hello` }; export const lazy = < ModuleShape, ExportName extends keyof ModuleShape = keyof ModuleShape >(module: ModuleShape, exportName: ExportName) => { return module[exportName]; }; const lazyMessage = lazy(myModule, 'message'); // TypeScript 能识别这是 string 类型 console.log(lazyMessage);
临时解决方案(冗余)
我可以通过同时传入导出名称作为泛型参数来获得正确的具体类型,但这样需要重复写两次导出名称,显得冗余:
修改后的 lazy.ts
// lazy.ts export const lazy = async< ModuleShape, ExportName extends keyof ModuleShape = keyof ModuleShape >( path: string, exportName: ExportName, ) => { const module = await import(path) as ModuleShape; // 执行副作用后... return module[exportName]; };
使用方式(冗余)
// main.ts // 必须重复写两次 `message` const lazyMessage = await lazy<typeof myModule, 'message'>('./myModule.ts', 'message');
疑问
为什么 TypeScript 在第一种懒加载模块的场景下,无法像推断普通对象属性那样正确导出项的类型?
内容的提问来源于stack exchange,提问作者RobertAKARobin
相关产品推荐
相关产品推荐

