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

如何借助TypeScript Interface验证输入的JSON数组并生成错误?

如何在运行时基于TypeScript接口验证JSON数组并生成错误信息

TypeScript接口仅存在于编译阶段,编译后会被完全擦除,因此无法通过instanceof这类运行时操作校验类型。我们需要手动编写运行时校验函数,模拟接口的类型规则,同时生成具体的错误信息。

实现思路

  1. 针对每个接口(如Address、Employee)编写单独的校验函数,检查字段类型、必填性、枚举值范围;
  2. 校验数组时遍历每个元素,收集所有错误(而非遇到第一个错误就返回);
  3. 支持检测未知字段(可选,根据需求决定是否允许额外字段);
  4. 返回包含元素索引和错误描述的结构化错误信息,方便定位问题。

完整校验代码

// 定义错误信息结构
interface ValidationError {
  index: number; // 数组元素索引(-1表示整体输入错误)
  message: string; // 具体错误描述
}

interface Employee {
  name: string;
  age: number;
  email: string;
  address?: Address;
  role?: roleType;
}

interface Address {
  city: string;
  pinCode: number;
}

type roleType = 'Developer' | 'UI Designer';

// 校验Address对象
function validateAddress(address: any): string | null {
  if (typeof address !== 'object' || address === null) {
    return 'address必须是对象类型';
  }
  // 检查必填字段类型
  if (typeof address.city !== 'string') {
    return 'address.city必须是字符串类型';
  }
  if (typeof address.pinCode !== 'number' || !Number.isInteger(address.pinCode)) {
    return 'address.pinCode必须是整数类型';
  }
  // 检测未知字段(可选,不需要可删除)
  const allowedAddressKeys = ['city', 'pinCode'];
  const extraKeys = Object.keys(address).filter(key => !allowedAddressKeys.includes(key));
  if (extraKeys.length > 0) {
    return `address包含未知字段: ${extraKeys.join(', ')}`;
  }
  return null;
}

// 校验Employee对象
const validRoles: roleType[] = ['Developer', 'UI Designer'];
function validateEmployee(employee: any): string | null {
  if (typeof employee !== 'object' || employee === null) {
    return '必须是对象类型';
  }
  // 检查必填字段
  if (typeof employee.name !== 'string') {
    return 'name必须是字符串类型';
  }
  if (typeof employee.age !== 'number' || !Number.isInteger(employee.age) || employee.age <= 0) {
    return 'age必须是正整数类型';
  }
  // 简单邮箱格式校验(可根据需求增强正则)
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
  if (typeof employee.email !== 'string' || !emailRegex.test(employee.email)) {
    return 'email格式不合法';
  }
  // 校验可选的address字段
  if (employee.address !== undefined) {
    const addressError = validateAddress(employee.address);
    if (addressError) return addressError;
  }
  // 校验可选的role字段
  if (employee.role !== undefined) {
    if (!validRoles.includes(employee.role)) {
      return `role必须是以下值之一: ${validRoles.join(', ')}`;
    }
  }
  // 检测未知字段(可选,不需要可删除)
  const allowedEmployeeKeys = ['name', 'age', 'email', 'address', 'role'];
  const extraKeys = Object.keys(employee).filter(key => !allowedEmployeeKeys.includes(key));
  if (extraKeys.length > 0) {
    return `包含未知字段: ${extraKeys.join(', ')}`;
  }
  return null;
}

// 校验整个Employee数组
function validateEmployeeArray(input: any): ValidationError[] {
  const errors: ValidationError[] = [];
  // 先检查输入是否为数组
  if (!Array.isArray(input)) {
    errors.push({ index: -1, message: '输入不是合法的JSON数组' });
    return errors;
  }
  // 遍历每个元素校验
  input.forEach((item, index) => {
    const errorMsg = validateEmployee(item);
    if (errorMsg) {
      errors.push({ index, message: `第${index + 1}个元素: ${errorMsg}` });
    }
  });
  return errors;
}

使用示例(结合textarea输入)

// 从textarea获取输入并解析
const textarea = document.querySelector('textarea');
if (textarea) {
  const inputValue = textarea.value;
  try {
    const parsedData = JSON.parse(inputValue);
    const validationErrors = validateEmployeeArray(parsedData);
    
    if (validationErrors.length === 0) {
      console.log('所有数据校验通过');
      // 断言为Employee[]类型继续业务逻辑
      const validEmployees = parsedData as Employee[];
      // ...后续处理
    } else {
      console.error('校验失败:', validationErrors);
      // 将错误展示给用户(示例:输出到控制台)
      validationErrors.forEach(err => console.error(err.message));
    }
  } catch (e) {
    console.error('JSON解析失败:', (e as Error).message);
  }
}

关键说明

  • instanceof失效原因:TypeScript接口仅用于编译时类型检查,编译后的JS代码中不会保留接口定义,因此没有对应的构造函数供instanceof判断;
  • 可选字段处理:通过判断字段是否为undefined,再触发对应的子校验;
  • 枚举类型校验:将roleType的有效值存入数组,通过includes方法检查输入值是否合法;
  • 未知字段检测:通过对比允许的字段列表,过滤出多余字段,避免不符合接口的数据流入业务逻辑(不需要可删除该逻辑)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 12:45:12