如何修复TypeScript NodeNext解析模式下的默认导入问题?
问题根源
启用NodeNext模块解析后,TypeScript会严格区分ES模块与CommonJS模块的导出格式。尽管@spectrum-icons/workflow的实际代码是ES模块的default导出,但TypeScript在该模式下误判了模块类型,将导入的Contrast识别为包含default属性的对象(类似CommonJS导出逻辑),而非直接的React组件函数,因此抛出"Contrast cannot be used as a JSX component"错误。
解决方案
方案1:添加项目级类型补丁
在项目根目录创建types/spectrum-icons-workflow.d.ts文件,手动修正模块导出类型,强制TypeScript将其识别为ES模块的default导出:
declare module '@spectrum-icons/workflow/*' { import { IconPropsWithoutChildren } from '@react-spectrum/icon'; import React from 'react'; const IconComponent: (props: IconPropsWithoutChildren) => React.JSX.Element; export default IconComponent; }
随后在tsconfig.json中配置typeRoots,让TypeScript识别这个自定义类型文件:
{ "compilerOptions": { // 其他原有配置... "typeRoots": ["./types", "./node_modules/@types"] } }
该方案无需修改业务代码,直接从类型层面解决不匹配问题,是最彻底的处理方式。
方案2:调整导入语法(临时 workaround)
若不想添加类型补丁,可通过import * as语法导入,显式提取default并添加类型断言,绕开TypeScript的解析错误:
import * as ContrastModule from '@spectrum-icons/workflow/Contrast'; const Contrast = ContrastModule.default as (props: import('@react-spectrum/icon').IconPropsWithoutChildren) => React.ReactElement; export function AppHeader(_props: AppHeaderProps) { return ( <Header> <ActionButton> <Contrast /> </ActionButton> </Header> ); }
这种方式需要每个图标导入都重复操作,适合临时应急场景。
方案3:检查包的模块配置(可选)
查看node_modules/@spectrum-icons/workflow/package.json中的exports字段,确认是否正确配置了ES模块的导出路径及对应类型文件。若包本身的模块配置缺失或错误,也会导致NodeNext模式下的类型解析问题,此时可向包仓库提交issue,请求维护者完善NodeNext兼容配置。
内容的提问来源于stack exchange,提问作者Harshal Patil

