从TypeScript对象获取JSX Element时遇到类型错误的问题
TypeScript + React 图标映射函数的类型错误解决方法
问题代码与报错
定义的图标映射对象(state.ts)
import { IconCalendarEvent, TablerIcon, IconRun } from "@tabler/icons"; export const StateIcon = { Validated: IconCalendarEvent, Running: IconRun };
TypeScript自动推断的类型:
const StateIcon: { Validated: TablerIcon; Running: TablerIcon; }
尝试的第一个函数及报错
想根据状态字符串返回对应JSX图标组件,写了如下函数:
const getIcon = (state: string) => { const r = (_.keys(StateIcon) as (keyof typeof StateIcon)[]).find((k) => { return k === state; }); return <StateIcon[r] /> };
报错信息:
JSX element type 'StateIcon' does not have any construct or call signatures
尝试的第二个函数及报错
修改后代码:
const getIcon = (state: string) => { const Icon = StateIcon[state]; return <Icon />; };
报错信息:
Element implicitly has an 'any' type because expression of type
'string' can't be used to index type '{ Validated: TablerIcon;
Running: TablerIcon; }'. No index signature with a parameter of type
'string' was found on type '{ Validated: TablerIcon; Running:
TablerIcon; }'
忽略的关键点与解决方法
1. JSX组件的引用规则与类型推断
React要求组件必须以大写字母开头命名,TypeScript也依赖这个规则识别可调用的组件类型:
- 直接写
<StateIcon[r] />时,TS无法把动态访问的属性识别为合法组件,且r可能为undefined(若state匹配不到任何键),TS会误认为你在调用StateIcon本身而非它的属性。 - 解决:把动态获取的组件赋值给大写开头的变量,再用该变量渲染JSX。
2. 索引类型的收窄
state: string类型过于宽泛,TS无法确认它是StateIcon的合法键,因此会报索引类型不匹配错误:
- 解决:要么限制参数类型为
StateIcon的键类型,要么通过类型检查做类型收窄。
正确写法示例
方法一:限制参数为合法键类型(推荐,适用于state来自代码内部的场景)
const getIcon = (state: keyof typeof StateIcon) => { // 赋值给大写开头的变量,TS能识别为组件类型 const IconComponent = StateIcon[state]; return <IconComponent />; };
方法二:处理任意string类型的state(适用于state来自外部,比如后端返回的场景)
const getIcon = (state: string) => { // 先检查state是否是StateIcon的合法键 if (!(state in StateIcon)) { // 可返回默认图标或null return null; } // 类型断言后获取组件 const IconComponent = StateIcon[state as keyof typeof StateIcon]; return <IconComponent />; };
内容的提问来源于stack exchange,提问作者curiousguy
相关产品推荐
相关产品推荐

