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

如何使用TypeScript条件类型验证对象数组的结构正确性?

问题与解决方案

问题描述

我们的应用通过条件类型基于对象的type属性处理对象数组的结构,用这些对象定义操作序列供引擎执行。但当前代码中,当对象的type为Payloads.B时,传入不符合要求的propA作为payload属性,TypeScript类型检查器并未抛出错误,无法自动验证payload的正确性。

原代码示例:

type payloadA = {
  propA: string;
}

type payloadB = {
  propB: boolean;
}

enum Payloads {
  A = 'A',
  B = 'B',
}

type conditionalPayload<T extends Payloads> =
  T extends Payloads.A ? payloadA
  : T extends Payloads.B ? payloadB
  : never;

type myObj<T extends Payloads> = {
  type: T;
  payload: conditionalPayload<T>
}

// 使用数组的数组结构,与实际代码一致
const myArray: myObj<Payloads>[][] = [
  [
    {
      type: Payloads.A,
      payload: {
        propA: 'dummy',
      },
    },
    {
      type: Payloads.B,
      payload: {
        propA: 'dummy', // 期望此处报错,但当前未触发
      },
    },
  ],
];

问题原因

当把myObj<Payloads>作为数组元素类型时,TypeScript会将其解析为单一对象类型:{ type: Payloads; payload: payloadA | payloadB },而非我们期望的myObj<Payloads.A> | myObj<Payloads.B>联合类型。这意味着类型检查器只会验证type属于Payloads、payload属于payloadA或payloadB,不会强制type与payload的结构一一对应。

解决方案

我们需要让操作类型成为严格的联合类型,确保每个操作的type和对应payload强绑定。有两种实现方式:

方式一:直接定义联合类型

显式列出所有操作类型的联合,让TypeScript严格检查每个元素必须匹配联合中的某一个完整结构:

type payloadA = {
  propA: string;
}

type payloadB = {
  propB: boolean;
}

enum Payloads {
  A = 'A',
  B = 'B',
}

// 定义所有合法操作的联合类型
type Operation =
  | { type: Payloads.A; payload: payloadA }
  | { type: Payloads.B; payload: payloadB };

// 数组类型改为 Operation[][]
const myArray: Operation[][] = [
  [
    {
      type: Payloads.A,
      payload: {
        propA: 'dummy',
      },
    },
    {
      type: Payloads.B,
      payload: {
        propA: 'dummy', // 此处会立即触发类型错误,符合预期
      },
    },
  ],
];

方式二:利用映射类型生成联合类型

如果操作类型较多,可通过映射类型自动生成联合类型,避免重复编写:

type payloadA = {
  propA: string;
}

type payloadB = {
  propB: boolean;
}

enum Payloads {
  A = 'A',
  B = 'B',
}

type conditionalPayload<T extends Payloads> =
  T extends Payloads.A ? payloadA
  : T extends Payloads.B ? payloadB
  : never;

type myObj<T extends Payloads> = {
  type: T;
  payload: conditionalPayload<T>
}

// 通过映射类型生成所有 myObj<T> 的联合类型
type Operation = { [K in Payloads]: myObj<K> }[Payloads];

const myArray: Operation[][] = [
  [
    {
      type: Payloads.A,
      payload: {
        propA: 'dummy',
      },
    },
    {
      type: Payloads.B,
      payload: {
        propA: 'dummy', // 此处触发类型错误
      },
    },
  ],
];

两种方式都能让TypeScript强制验证每个操作的type与payload结构严格匹配,当传入不符合的payload时立即抛出类型错误。

内容的提问来源于stack exchange,提问作者Jesus Diaz Rivero

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 04:36:05