如何以类型安全方式访问对象中指定的数组类型属性?
解决TypeScript中安全访问对象数组属性的问题
这个报错的核心原因是,Object.keys()返回的类型是string[],而非我们定义的Possibles类型集合。TypeScript没法推断出这些字符串key对应的myFilter属性一定是数组,所以会把属性类型解析成Filter接口所有值类型的联合类型(包含number这种没有length属性的类型),从而抛出TS2339错误。
我们可以通过类型断言结合已有的类型定义,实现类型安全的数组访问,具体修改如下:
const resetFilter = () => { // 明确断言key集合为Possibles类型数组,因为我们知道filterNameLookup的key严格属于这个类型 const possibleKeys = Object.keys(filterNameLookup) as Possibles[]; possibleKeys.forEach((key) => { // 此时key是Possibles类型,TypeScript能确定myFilter[key]是数组类型 const possibleOptions = myFilter[key]; // filterNameLookup[key]是IDs类型,对应的myFilter属性也是number[]数组 const selectedIds = myFilter[filterNameLookup[key]]; if (possibleOptions.length === selectedIds.length) { selectedIds.length = 0; } }); };
为什么这样能解决问题?
- 类型断言缩小范围:把
Object.keys(filterNameLookup)断言为Possibles[],告诉TypeScript这些key都是我们预先定义好的、对应数组属性的字段,排除了其他非数组属性的可能性。 - 利用已有类型关联:
Possibles和IDs类型已经明确了哪些属性是数组,TypeScript可以根据这些类型定义,确定myFilter[key]和myFilter[filterNameLookup[key]]都是数组,从而安全访问length属性。
运行修改后的resetFilter()后,就能得到你期望的结果:那些选中ID数组长度和可选选项数组长度完全一致的字段(比如cropTypeIds、fieldIds)会被清空,其他字段保留原有值。
内容的提问来源于stack exchange,提问作者user2115620
相关产品推荐
相关产品推荐

