You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 16:40:01