TypeScript报错:string|number无法索引IStorage类型如何指定索引签名
TypeScript 访问IStorage接口属性索引报错修复方案
报错信息
Element implicitly has an 'any' type because expression of type 'string | number' can't be used to index type 'IStorage'. No index signature with a parameter of type 'string' was found on type 'IStorage'.
问题根因
报错触发位置为storage[index][event.name]。TS静态检查时发现,event.name的类型是宽泛的string | number,但IStorage接口仅声明了固定的已知属性,未定义兼容任意字符串/数字入参的索引签名,TS无法确认传入的键一定属于IStorage的合法属性,同时也无法校验赋值的event.value和对应属性的类型是否匹配,因此抛出错误。
涉及的原有代码:IStorage接口定义:
interface IStorage { id: number name: string vendor_id: string start_date: Date | null end_date: Date | null app: string }
事件处理函数:
handleSetStorageValues = (index: number) => (event: { name: string | number value: string | number }) => { const storage = [...this.state.storage] storage[index][event.name] = event.value // 报错行 this.setState( prevState => { return { ...prevState, storage, } } ) }
正确修复方式
不推荐直接给IStorage添加[key: string]: any这类宽泛索引签名,这种写法会丢失所有属性的类型校验能力,后续属性赋值出错TS无法提示。
正确方案是通过泛型收窄类型,将event.name约束为IStorage的合法属性名,同时保证event.value的类型和对应属性的类型匹配:
- 用TS内置的
keyof操作符获取IStorage所有合法属性名的联合类型,再通过泛型约束事件参数的类型,修改后的事件处理函数如下:
handleSetStorageValues = (index: number) => <K extends keyof IStorage>(event: { name: K value: IStorage[K] }) => { const storage = [...this.state.storage] // 此时TS可识别event.name为IStorage的合法属性,索引报错消失 storage[index][event.name] = event.value this.setState( prevState => ({ ...prevState, storage, }) ) }
- 配套调整表单控件的name属性类型,确保传入的name值一定属于
IStorage的属性名,避免传入非法字段名。如果是日期类字段(start_date/end_date),需保证对应控件返回的value类型为Date | null,和接口定义一致;如果是普通输入框返回字符串/数字,需在赋值前做对应类型转换,避免类型不匹配。
内容的提问来源于stack exchange,提问作者John McGellan
相关产品推荐
相关产品推荐

