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

如何基于函数参数值推断TypeScript类型及处理多类型回调?

TypeScript数据流函数的类型推断与多类型回调实践

一、根据Enum参数值推断Message类型

要让TypeScript根据variable的具体枚举值自动推断message类型,函数重载和泛型+映射类型是两种可靠的解决方案,分别适合不同场景:

1. 函数重载方案

先定义枚举和对应消息类型,再为每个枚举值单独声明重载签名,实现时统一处理:

enum SomeEnum {
  Foo,
  Bar
}

type FooMessage = { type: 'foo'; content: string };
type BarMessage = { type: 'bar'; value: number };

// 重载签名:为每个枚举值指定对应回调类型
function stream(variable: SomeEnum.Foo, callback: (message: FooMessage) => void): void;
function stream(variable: SomeEnum.Bar, callback: (message: BarMessage) => void): void;

// 实现签名:兼容所有情况的兜底逻辑
function stream(variable: SomeEnum, callback: (message: FooMessage | BarMessage) => void): void {
  // 数据流订阅逻辑
}

// 调用时自动推断类型
stream(SomeEnum.Foo, (msg) => {
  console.log(msg.content); // 类型推断为FooMessage,可直接访问content
});

2. 泛型+映射类型方案

通过映射类型建立枚举值到消息类型的关联,扩展性更强,新增枚举值只需更新映射:

enum SomeEnum {
  Foo,
  Bar
}

type FooMessage = { type: 'foo'; content: string };
type BarMessage = { type: 'bar'; value: number };

// 定义枚举到消息类型的映射
type EnumToMessage = {
  [SomeEnum.Foo]: FooMessage;
  [SomeEnum.Bar]: BarMessage;
};

// 泛型函数自动推导对应类型
function stream<T extends SomeEnum>(variable: T, callback: (message: EnumToMessage[T]) => void): void {
  // 数据流订阅逻辑
}

// 调用时自动推断类型
stream(SomeEnum.Bar, (msg) => {
  console.log(msg.value); // 类型推断为BarMessage,可直接访问value
});

二、多类型返回场景的回调选择

是否拆分两个回调,取决于业务逻辑的独立性:

  • 如果两种类型的处理逻辑完全分离(比如Type1是日志、Type2是业务数据),拆分两个回调会让代码更清晰,避免在单个回调中写大量类型判断;
  • 如果两种类型需要统一处理(比如都要做解析后存储),使用联合类型的单个回调更简洁。

用重载/泛型适配多类型场景

无论选择哪种回调方式,重载和泛型都能解决类型推断问题:

1. 单回调(联合类型)场景

enum SomeEnum {
  Mixed // 返回Type1 | Type2
}

type Type1 = { type: 'type1'; log: string };
type Type2 = { type: 'type2'; data: number };

// 重载方案
function stream(variable: SomeEnum.Mixed, callback: (message: Type1 | Type2) => void): void;

// 泛型映射方案
type EnumToMessage = {
  [SomeEnum.Mixed]: Type1 | Type2;
};
function stream<T extends SomeEnum>(variable: T, callback: (message: EnumToMessage[T]) => void): void;

2. 双回调场景

通过泛型条件类型,让函数根据枚举值自动要求对应回调参数:

enum SomeEnum {
  Mixed,
  Foo
}

type Type1 = { type: 'type1'; log: string };
type Type2 = { type: 'type2'; data: number };
type FooMessage = { type: 'foo'; content: string };

function stream<T extends SomeEnum>(
  variable: T,
  callbacks: T extends SomeEnum.Mixed 
    ? { onType1: (msg: Type1) => void; onType2: (msg: Type2) => void }
    : { onMessage: (msg: FooMessage) => void }
): void {
  // 实现时根据variable类型调用对应回调
}

// 调用Mixed时必须传两个回调
stream(SomeEnum.Mixed, {
  onType1: (msg) => console.log(msg.log),
  onType2: (msg) => console.log(msg.data)
});

// 调用Foo时只需传单个回调
stream(SomeEnum.Foo, {
  onMessage: (msg) => console.log(msg.content)
});

总结

  • 枚举值对应单一消息类型:泛型+映射类型扩展性更强,函数重载更直观;
  • 多类型返回场景:拆分回调适合逻辑独立的情况,联合类型回调适合统一处理的场景;
  • 重载和泛型都能解决类型推断问题,泛型更适合复杂的类型映射场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 05:43:20