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

TypeScript映射含enum属性的JSON为TS类型对象报错问题

问题原因

你遇到的类型错误来自两个写法问题:

  1. 函数入参类型声明错误:从API拉取的JSON解析后,type字段是普通string类型,本身并不符合Seat类型要求的SEAT_TYPE枚举约束,你把convert的入参直接声明为Array<Seat>,传入原始解析数据时TS自然会报类型不匹配。
  2. 类型断言写法错误:as keyof typeof SEAT_TYPE取的是枚举的键名联合类型,不是枚举本身的类型,在你的字符串枚举场景下虽然键名和值刚好重名,但属于歪打正着,换数字枚举或者值与键名不同的枚举就会出问题。

另外要注意:TS的类型断言只在编译阶段做类型检查欺骗,不会在运行时做任何类型转换,生产环境下不能完全信任后端返回值,最好加枚举合法性校验。

正确实现代码

首先定义接口返回的原始数据类型,和业务模型做区分:

// 接口返回的原始座位数据,type字段为普通字符串
type RawSeat = {
  number: string;
  type: string;
  status: boolean;
};

export enum SEAT_TYPE {
  ECONOMY = "ECONOMY",
  PREMIUM_ECONOMY = "PREMIUM_ECONOMY",
  BUSINESS = "BUSINESS",
}

export type Seat = {
  number: string;
  type: SEAT_TYPE;
  status: boolean;
};

export class SeatingPlan {
  seating: Seat[] = [];
}

然后修正转换函数,加入可选的合法性校验:

export function convert(json: Array<RawSeat>): Seat[] {
  return json.map((seat) => {
    // 校验座位类型是否合法,避免后端返回脏数据
    const isValidSeatType = Object.values(SEAT_TYPE).includes(seat.type as SEAT_TYPE);
    if (!isValidSeatType) {
      throw new Error(`解析座位数据失败,非法座位类型:${seat.type}`);
    }

    return {
      number: seat.number,
      type: seat.type as SEAT_TYPE, // 校验通过后再断言为枚举类型
      status: seat.status,
    };
  });
}

调用时先解析JSON再传入即可,不会再有类型错误:

// 解析接口返回的JSON字符串
const rawSeatData = JSON.parse(apiResponse) as RawSeat[];
// 转换为标准Seat类型数组
const seatList = convert(rawSeatData);

// 填充到座位表实例
const seatingPlan = new SeatingPlan();
seatingPlan.seating = seatList;
简化写法(不推荐生产环境使用)

如果你可以100%确定后端返回的type值一定属于SEAT_TYPE枚举的合法值,可以跳过校验直接转换,代码更简洁:

export function convert(json: Array<Omit<Seat, 'type'> & {type: string}>): Seat[] {
  return json.map(seat => ({
    ...seat,
    type: seat.type as SEAT_TYPE
  }));
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 19:48:23