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

TypeScript遍历嵌套对象提取含required键的对象键时的类型错误解决

问题描述

我定义了如下TypeScript类型:

export type DataType = {
  id: string;
  type: string;
  'product-configuration': { inputs: ConfigurationType };
};

export type ConfigurationType = {
  [key: string]: ItemDataType;
};

export type ItemDataType = {
  required: boolean;
  type: string;
  hint?: string;
  constraint?: ConstraintType;
  options?: string[];
  conditional?: ConditionalItemDataType;
};

export type ConstraintType = {
  min?: number;
  max?: number;
  format?: string;
};

export type ConditionalItemType = [
  { condition: string },
  { [key: string]: ItemDataType }
];

export type ConditionalItemDataType = ConditionalItemType[];

同时有一个符合该类型的对象:

const abc = {
  id: 45,
  type: 'product',
  'product-configuration': {
    inputs: {
      'Instance Name': {
        required: true,
        type: 'text',
        constraint: {
          min: 3,
          max: 15,
          format: 'alpha-hyphen-numeric',
        },
      },
      Environment: {
        required: true,
        type: 'select',
        options: ['Prod', 'Dev'],
      },
      'Content Type': {
        required: true,
        type: 'select',
        options: ['Markdown', 'HTML'],
        conditional: [
          [
            { condition: 'Markdown' },
            {
              'Folder Location': {
                required: true,
                type: 'text',
                constraint: {
                  max: 30,
                },
              },
            },
          ],
        ],
      },
      'Content folder path': {
        required: false,
        type: 'select',
        options: ['Root', 'Content'],
      },
      'Start Date': {
        required: true,
        type: 'date',
      },
      'Need Playground': {
        required: false,
        type: 'select',
        options: ['Yes', 'No'],
      },
    },
  },
};

我想要提取所有包含required键的对象的键名,为此编写了如下代码,该代码在JavaScript中运行正常,但在TypeScript中出现类型错误。我通过将typeof obj[key] === 'object'修改为typeof obj[key as keyof DataType] === 'object'消除了第一个错误,但无法解决另外两个错误。若使用obj: any可消除前两个错误,但第三个错误仍存在,且我不想使用any。请问如何在不使用any的情况下解决这些类型错误?

原代码:

const findFieldNames = (obj, result = [], currentPath = '') => {
  for (const key in obj) {    
    const newPath = currentPath ? `${currentPath}.${key}` : key;
    if (typeof obj[key] === 'object') {
          findFieldNames(obj[key], result, newPath);
    } else if (key === 'required') {
      result.push(newPath.match(/(?<=\.)([^.]+)(?=\.required$)/)[0]);
    }
  }
  return result;
}
解决方案

1. 定义覆盖所有遍历场景的联合类型

首先,我们需要明确函数要处理的所有可能结构,定义一个联合类型来替代any:

type TraversableType = 
  | DataType 
  | ConfigurationType 
  | ItemDataType 
  | ConstraintType 
  | ConditionalItemDataType 
  | ConditionalItemType 
  | { [key: string]: ItemDataType };

2. 修正类型安全的遍历逻辑

  • 使用keyof typeof obj确保遍历的键合法
  • 添加value !== null判断,因为typeof null也会返回object,但我们不需要遍历null
  • 处理正则匹配的空值风险,避免直接访问match[0]导致的报错

最终修改后的代码

type TraversableType = 
  | DataType 
  | ConfigurationType 
  | ItemDataType 
  | ConstraintType 
  | ConditionalItemDataType 
  | ConditionalItemType 
  | { [key: string]: ItemDataType };

const findFieldNames = (obj: TraversableType, result: string[] = [], currentPath = '') => {
  for (const key in obj) {
    const value = obj[key as keyof typeof obj];
    const newPath = currentPath ? `${currentPath}.${key}` : key;
    
    // 仅遍历非空的对象或数组
    if (typeof value === 'object' && value !== null) {
      findFieldNames(value as TraversableType, result, newPath);
    } else if (key === 'required') {
      const match = newPath.match(/(?<=\.)([^.]+)(?=\.required$)/);
      // 确保匹配成功再提取结果
      if (match) {
        result.push(match[0]);
      }
    }
  }
  return result;
};

关键说明

  • 联合类型TraversableType:覆盖了所有需要递归遍历的结构,让TypeScript能识别参数的合法范围,避免any的滥用
  • 空值过滤:排除null,避免无效的递归调用
  • 正则匹配安全处理:先检查匹配结果是否存在,解决TypeScript对可能null值的报错,同时提升代码健壮性

测试调用示例:

const requiredFields = findFieldNames(abc as DataType);
console.log(requiredFields); // 输出: ["Instance Name", "Environment", "Content Type", "Folder Location", "Start Date"]

内容的提问来源于stack exchange,提问作者moys

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 02:16:05