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

TypeScript泛型动态函数参数:如何获取第二个参数的正确类型?

TypeScript泛型函数内部无法根据第一个参数推断第二个参数类型的解决方法

我参考教程在TypeScript中用泛型实现了动态参数的sendEvent函数,外部调用时参数类型符合预期,但函数内部第二个参数eventPayload的类型始终是unknown。如何根据第一个参数的类型,在函数内部获取第二个参数的正确类型?

相关代码:

export type Event =
  | { type: "LOG_IN"; payload: { userId: string } }
  | { type: "SIGN_OUT" };


const sendEvent = <Type extends Event["type"]>(
  ...args: Extract<Event, { type: Type }> extends { payload: infer TPayload }
    ? [type: Type, payload: TPayload]
    : [type: Type]
) => {
  const eventType = args[0]; // 类型为 "LOG_IN" | "SIGN_OUT"
  const eventPayload = args[1]; // 类型为 unknown
  // 如何让eventPayload获得对应payload的正确类型?
};

解决方案1:使用类型守卫窄化类型

在函数内部通过判断eventType的具体值,TypeScript会自动关联并窄化eventPayload的类型:

const sendEvent = <Type extends Event["type"]>(
  ...args: Extract<Event, { type: Type }> extends { payload: infer TPayload }
    ? [type: Type, payload: TPayload]
    : [type: Type]
) => {
  const eventType = args[0];
  
  if (eventType === "LOG_IN") {
    const eventPayload = args[1]; // 类型自动推断为 { userId: string }
    console.log(eventPayload.userId); // 无类型错误
  } else if (eventType === "SIGN_OUT") {
    const eventPayload = args[1]; // 类型自动推断为 undefined
    // 无需处理payload
  }
};

解决方案2:重构为对象参数(推荐)

将参数改为单个对象形式,TypeScript的类型推断逻辑会更清晰,内部直接解构就能拿到对应类型:

export type Event =
  | { type: "LOG_IN"; payload: { userId: string } }
  | { type: "SIGN_OUT" };

const sendEvent = <E extends Event>(event: E) => {
  const { type: eventType, payload: eventPayload } = event;
  
  if (eventType === "LOG_IN") {
    console.log(eventPayload.userId); // 类型正确
  }
};

// 调用示例
sendEvent({ type: "LOG_IN", payload: { userId: "user_123" } });
sendEvent({ type: "SIGN_OUT" });

解决方案3:定义事件类型映射

提前构建事件类型到payload的映射关系,通过泛型直接获取对应类型:

export type Event =
  | { type: "LOG_IN"; payload: { userId: string } }
  | { type: "SIGN_OUT" };

// 建立事件类型与payload的映射
type EventPayloadMap = {
  [E in Event as E["type"]]: E extends { payload: infer P } ? P : undefined;
};

const sendEvent = <Type extends Event["type"]>(
  ...args: EventPayloadMap[Type] extends undefined 
    ? [type: Type] 
    : [type: Type, payload: EventPayloadMap[Type]]
) => {
  const eventType = args[0];
  const eventPayload = args[1] as EventPayloadMap[Type];
  
  if (eventType === "LOG_IN") {
    console.log(eventPayload.userId); // 类型正确
  }
};

问题原因

原写法中,泛型Type在函数内部是宽泛的联合类型("LOG_IN" | "SIGN_OUT"),TypeScript无法从元组args中建立args[0]和args[1]的类型关联,导致args[1]被推断为unknown。通过上述三种方案,能让TypeScript明确参数之间的类型依赖关系。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 16:15:42