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

如何让TypeScript中createEventOnTopic函数的第一个参数约束第二个参数的合法事件类型?

实现Topic与Event的类型关联

当然可以实现!我们可以利用TypeScript的泛型和映射类型,让第一个参数topic的取值直接约束第二个参数message中event的可选值,在编译阶段就拦截不匹配的组合。

步骤1:建立Topic到Event的类型映射

首先我们需要明确每个Topic对应的合法Event集合,用一个映射类型把它们关联起来:

const topics = ['topic-1', 'topic-2'] as const;
export type Topic = typeof topics[any];

const eventsTopic1 = ['add_something', 'remove_something'] as const;
export type EventTopic1 = typeof eventsTopic1[any];

const eventsTopic2 = ['add_anything', 'remove_anything'] as const;
export type EventTopic2 = typeof eventsTopic2[any];

// 核心:定义Topic与对应Event类型的映射关系
type TopicToEventMap = {
  'topic-1': EventTopic1;
  'topic-2': EventTopic2;
};

步骤2:改造Message为泛型接口

把原来的Message接口改成泛型,让它的event字段类型可以动态传入:

export interface Message<E extends string> {
  event: E;
  data: any;
}

步骤3:用泛型约束函数参数

修改createEventOnTopic函数,通过泛型捕获传入的具体Topic值,再通过映射类型获取对应的Event类型,从而约束message的结构:

function createEventOnTopic<T extends Topic>(topic: T, message: Message<TopicToEventMap[T]>): void { }

测试效果

现在调用函数时,TypeScript会自动校验event是否匹配所选的topic:

createEventOnTopic('topic-1', { event: 'add_something', data: 'any' }); // ✅ 完全合法
createEventOnTopic('topic-1', { event: 'add_anything', data: 'any' }); // ❌ 报错:类型'"add_anything"'不能赋值给类型'"add_something" | "remove_something"'
createEventOnTopic('topic-2', { event: 'add_anything', data: 'any' }); // ✅ 完全合法

可选优化:让Data类型也与Event关联

如果不同的Event需要对应不同的Data结构,我们可以进一步扩展映射关系,让类型约束更严谨:

// 扩展映射,包含每个Event对应的Data类型
type TopicToEventDetailsMap = {
  'topic-1': {
    'add_something': { id: string; name: string },
    'remove_something': { id: string }
  };
  'topic-2': {
    'add_anything': { content: string },
    'remove_anything': { uuid: string }
  };
};

// 重新定义Message接口,关联Event和Data类型
export interface Message<T extends Topic, E extends keyof TopicToEventDetailsMap[T]> {
  event: E;
  data: TopicToEventDetailsMap[T][E];
}

// 调整函数,支持更细粒度的类型约束
function createEventOnTopic<T extends Topic, E extends keyof TopicToEventDetailsMap[T]>(
  topic: T,
  message: Message<T, E>
): void { }

// 测试更严谨的约束
createEventOnTopic('topic-1', { event: 'add_something', data: { id: '1', name: 'test' } }); // ✅ 合法
createEventOnTopic('topic-1', { event: 'add_something', data: { id: '1' } }); // ❌ 报错:缺少必填字段'name'

这样不仅能约束Event与Topic的匹配,还能确保每个Event传入的Data结构完全符合要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 14:47:35