TypeScript报错:类型'string'不存在属性'title',索引签名含该属性
TypeScript索引签名类型收窄无效问题解决
你的问题核心在于:payload类型同时包含固定属性name和索引签名[id: string]: string | { title: string },当用levelID(类型为string)访问payload[levelID]时,TypeScript只能推断出值的类型是string | { title: string }。而你直接在条件判断和后续代码中重复调用e.tooltipPayload[0].payload[levelID],TypeScript无法确认这两次访问的是同一个值,导致类型收窄不生效。
解决方案
1. 将目标值存入变量后再做类型收窄
这是最简单有效的方法,把访问结果存到变量中,让TypeScript跟踪变量的类型变化:
const handleOpen = (e: HandleOpenEvent) => { const tooltipItem = e.tooltipPayload[0]; const levelID = tooltipItem.name; const target = tooltipItem.payload[levelID]; if (typeof target !== "string") { console.log(target.title); // 此处类型已正确收窄为{ title: string } // setDetailKey(target.title); } };
2. 使用自定义类型守卫函数(严谨场景)
如果需要更明确的类型校验,可以自定义类型守卫来判断值的结构:
function isTitleObject(obj: unknown): obj is { title: string } { return typeof obj === 'object' && obj !== null && 'title' in obj; } const handleOpen = (e: HandleOpenEvent) => { const tooltipItem = e.tooltipPayload[0]; const levelID = tooltipItem.name; const target = tooltipItem.payload[levelID]; if (isTitleObject(target)) { console.log(target.title); // setDetailKey(target.title); } };
3. 调整接口类型(从根源避免问题)
如果能确定payload中除了name之外的所有键对应的都是{ title: string }类型,可以修改接口定义,去掉索引签名的string类型:
export interface HandleOpenEvent { tooltipPayload: { dataKey: string; name: string; payload: { name: string; [id: string]: { title: string }; // 仅保留对象类型 }; }[]; }
修改后,访问payload[levelID]时TypeScript会直接推断为{ title: string },无需额外类型收窄。
注意事项
如果payload中确实存在部分键对应string类型,必须保留类型收窄逻辑,确保访问title前先排除string的情况,避免运行时错误。
内容的提问来源于stack exchange,提问作者ciel
相关产品推荐
相关产品推荐

