TypeScript按任意属性字符串过滤JSON数组报错求助
问题:过滤JSON对象数组中含指定关键词的对象
需求:将JSON对象数组绑定到网格,需要过滤出任意属性值(包括嵌套子对象/数组的属性)包含输入关键词的对象。
示例JSON(注意:该JSON存在重复键问题,解析时后序键会覆盖前序,建议修正):
[ { "TransactionID": "1", "MyProperty1": "some data 1", "MyProperty2": "28-02-2023", "MyProperty3": "some more data 1", "MyProperty4": "some other data 1", "documents": [ {"TransactionID": "1","MyProperty1":"Document 1","MyProperty2":"Completed"}, {"TransactionID": "1","MyProperty1":"Document 2","MyProperty2":"In Progress"}, {"TransactionID": "1","MyProperty1":"Document 3","MyProperty2":"In Progress"} ] }, { "TransactionID": "2", "MyProperty1": "some data 2", "MyProperty1": "27-02-2023", "MyProperty1": "some more data 2", "MyProperty1": "some other data 2", "documents": [ {"TransactionID": "2","MyProperty1":"Document 1","MyProperty1":"Completed"}, {"TransactionID": "2","MyProperty1":"Document 2","MyProperty1":"Completed"} ] } ]
尝试的代码及报错:
doFilter(filterText: string) { let filteredObject = this.engagementData.filter(o => Object.keys(o).some(k => o[k].toLowerCase().includes(filterText.toLowerCase()))); }
报错信息:'Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Object'
问题分析与解决
报错原因
TypeScript的类型检查机制导致:代码中的o被推断为Object类型,使用字符串k索引该对象时,TypeScript无法确定属性值的具体类型,因此抛出隐式any类型的错误。
解决方法
方法1:类型断言快速实现(适合快速验证)
将对象断言为Record<string, any>以允许字符串索引,同时处理值非字符串的情况(比如嵌套数组):
doFilter(filterText: string) { const lowerFilter = filterText.toLowerCase(); // 辅助函数:递归检查对象/数组的所有字符串属性 const matchesFilter = (item: any): boolean => { if (typeof item === 'string') { return item.toLowerCase().includes(lowerFilter); } if (Array.isArray(item)) { return item.some(subItem => matchesFilter(subItem)); } if (typeof item === 'object' && item !== null) { return Object.values(item).some(val => matchesFilter(val)); } return false; }; this.engagementData = this.engagementData.filter((o: Record<string, any>) => matchesFilter(o)); }
方法2:定义类型接口(类型安全,推荐)
先为数据结构定义TypeScript接口,明确属性类型后再进行过滤:
// 定义嵌套的文档接口 interface DocumentItem { TransactionID: string; MyProperty1: string; MyProperty2: string; } // 定义主交易对象接口 interface Transaction { TransactionID: string; MyProperty1: string; MyProperty2?: string; MyProperty3?: string; MyProperty4?: string; documents: DocumentItem[]; } // 确保engagementData的类型为Transaction[] engagementData: Transaction[] = []; doFilter(filterText: string) { const lowerFilter = filterText.toLowerCase(); this.engagementData = this.engagementData.filter(transaction => { // 检查当前交易的字符串属性 const matchesSelf = Object.values(transaction).some(val => { if (typeof val === 'string') { return val.toLowerCase().includes(lowerFilter); } return false; }); // 检查嵌套的documents数组 const matchesDocuments = transaction.documents.some(doc => Object.values(doc).some(val => val.toLowerCase().includes(lowerFilter)) ); return matchesSelf || matchesDocuments; }); }
关于内置函数的说明
JavaScript/TypeScript没有原生内置的“深度遍历对象并过滤”函数,但可以通过Object.keys/Object.values结合数组的some、filter方法封装通用工具函数,实现类似需求,上面的代码就是具体实现方式。
内容的提问来源于stack exchange,提问作者WorksOnMyLocal
相关产品推荐
相关产品推荐

