TypeScript 导入文件时无法为导入内容指定类型的问题如何解决?
解决方案
你遇到的类型报错是因为import * as Icons导入的模块对象默认没有匹配字符串索引的类型定义,TS无法识别你通过动态字符串索引取到的值是合法的React组件,可通过以下两种方法解决:
方法1:直接对导入对象做类型断言
直接在使用前给Icons对象声明类型,无需额外新增文件,改后代码如下:
import { capitalize } from "utils"; import React, { ComponentType, SVGProps } from "react"; import * as Icons from "./"; type IconProps = SVGProps<SVGSVGElement> & { name: string; }; const Icon = ({ name, ...props }: IconProps) => { const newName = capitalize(name); // 断言Icons的类型,明确键是字符串、值是接收SVG属性的React组件 const typedIcons = Icons as Record<string, ComponentType<SVGProps<SVGSVGElement>>>; if (!typedIcons[newName]) return null; const CustomIcon = typedIcons[newName]; return <CustomIcon {...props} />; }; export default Icon;
提示:React自定义组件名必须大写开头,原代码中小写的
icon作为组件名会被识别为原生DOM标签,建议统一修改为大写开头的Icon。
方法2:新增全局类型声明(适合长期维护)
如果该图标目录会被多处引用,可以在目录下新增index.d.ts类型声明文件,统一指定导出类型:
// 图标目录下的 index.d.ts import type { ComponentType, SVGProps } from "react"; declare module "./" { export = Record<string, ComponentType<SVGProps<SVGSVGElement>>>; }
配置后后续所有导入该目录的操作都会自动匹配上述类型,不需要单独做断言。
可选优化:严格校验图标名称
如果需要更严格的类型校验,避免传入不存在的图标名,可以手动枚举所有支持的图标名作为联合类型,替换掉name属性的string类型:
// 示例:假设支持home、user、setting三种图标 type IconName = 'home' | 'user' | 'setting'; type IconProps = SVGProps<SVGSVGElement> & { name: IconName; };
配置后TS会在开发阶段就提示非法的name传入,无需等到运行时判断返回null。
内容的提问来源于stack exchange,提问作者Yunus
相关产品推荐
相关产品推荐

