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

TypeScript泛型默认参数优化:实现无参空事件调用

解决TypeScript事件构造函数的无参数调用需求

你可以通过条件类型约束函数签名或者函数重载实现这个需求,让默认泛型(null)对应的事件构造函数支持无参数调用,同时保留带数据事件的类型校验。

方案一:条件类型约束函数返回值

通过条件类型判断泛型D是否为null,动态生成对应的函数签名:

export function defineEvent<D extends Record<string, any> | null = null>(name: string) {
  // 根据泛型D的类型,定义返回函数的类型
  type EventFn = D extends null ? () => null : (data: D) => D;

  const result = ((data?: D) => {
    // 无参数时返回null,有参数时返回传入的数据
    return data ?? null;
  }) as EventFn;

  result.$event = name;
  return result;
}

用法示例

  • 无数据事件(默认泛型):无需传参直接调用
const emptyEvent = defineEvent("testEvent");
emptyEvent(); // ✅ 正常调用,返回null
  • 带数据事件:保持原有类型校验和调用方式
const testEvent = defineEvent<{ name: string }>("testEvent");
testEvent({ name: "Bob" }); // ✅ 正常调用,返回传入的对象

方案二:函数重载

通过定义多个函数重载签名,明确区分无数据和带数据的事件构造函数:

// 重载签名1:无数据事件(默认场景)
export function defineEvent(name: string): () => null;
// 重载签名2:带数据事件(指定泛型)
export function defineEvent<D extends Record<string, any>>(name: string): (data: D) => D;

// 通用实现函数
export function defineEvent<D extends Record<string, any> | null = null>(name: string) {
  function result(data?: D) {
    return data ?? null;
  }
  result.$event = name;
  return result;
}

用法示例

和方案一完全一致,TypeScript会根据调用场景自动匹配对应的重载签名:

// 无数据事件
const emptyEvent = defineEvent("testEvent");
emptyEvent(); // ✅ 正常调用

// 带数据事件
const testEvent = defineEvent<{ age: number }>("ageEvent");
testEvent({ age: 25 }); // ✅ 正常调用

两种方案都能满足你的需求,方案一更依赖类型系统的条件判断,方案二更直观地通过重载区分不同场景,可根据个人习惯选择。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 23:20:19