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

TypeScript如何为可辨识联合类型定义强类型MessageHandler

强类型MessageHandler实现方案

核心问题

你当前的写法卡在无法将遍历到的type字面量和对应消息的payload类型关联,手动构造MessageVariant<T, Payload>需要额外维护type到payload的映射,属于冗余实现。

正确实现

利用TS内置的Extract工具类型,直接从Message判别联合中提取对应type的消息类型即可,不需要手动拼接泛型参数:

// 原有基础类型定义保持不变
type MessageVariant<T extends string, P = {}> = {
  type: T;
  payload: P;
};

type BoundsChangedMessage = MessageVariant<
  "bounds_changed",
  {
    bounds: number[][];
  }
>;

type ChangeLayoutMessage = MessageVariant<
  "change_layout",
  {
    name: string;
  }
>;

type Message = BoundsChangedMessage | ChangeLayoutMessage;

// 正确的MessageHandler类型定义
type MessageHandler = {
  [T in Message["type"]]: (message: Extract<Message, { type: T }>) => void;
};

类型校验效果

声明handlers对象时,TS会自动完成全链路类型推导和校验:

const handlers: MessageHandler = {
  bounds_changed: (message) => {
    // message自动推导为BoundsChangedMessage类型
    // 访问message.payload.bounds有完整类型提示,类型为number[][]
  },
  change_layout: (message) => {
    // message自动推导为ChangeLayoutMessage类型
    // 访问message.payload.name有完整类型提示,类型为string
  },
};

该实现自带以下校验能力:

  • 缺少任意一个消息type对应的处理函数时,TS会抛出类型错误
  • 新增不存在的type作为对象key时,TS会抛出类型错误
  • 处理函数内访问消息payload上不存在的属性时,TS会抛出类型错误
  • 后续新增Message联合的成员类型时,MessageHandler会自动适配,无需修改定义

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 19:36:33