将函数签名分配给 TypeScript 中的类型

Assign function signature to type in TypeScript

假设我有一个函数:

function registerEvent(event: Event, handler: HandlerSignature);

这些是各自的类型:

enum Event {
  EventOne,
  EventTwo
}

type HandlerSignature = (...args: any[]) => void;

现在每个事件都可以有不同的函数签名,例如:

function handler1(foo: number, bar: string);
function handler2(foo: string);

我想要实现的是我可以调用 registerEvent 函数,指定第一个 arg(事件)并让 TypeScript 检测哪个签名对应于此事件,即智能感知和防止用户为事件分配错误的签名。

我考虑过创建一个映射,在其中将不同的签名分配给枚举值,但我不能真正将其用作类型,可以吗?即使我使用映射类型,我也必须创建一个变量来分配所有事件。

我倾向于函数重载:

enum Events {
  EventOne,
  EventTwo
}

type HandlerSignature = (...args: any[]) => void;

function registerEvent(event: Events.EventOne, handler: (foo: number, bar: string) => void): void;
function registerEvent(event: Events.EventTwo, handler: (foo: number) => void): void;
function registerEvent(event: Events, handler: HandlerSignature):void {
    // ...implementation
}

function handler1(foo: number, bar: string) {}
function handler2(foo: string) {}

registerEvent(Events.EventOne, handler1); // Works
registerEvent(Events.EventOne, handler2); // Error as desired, wrong type for callback

Playground link

(注意我把Event改成了EventsEvent是一个预先存在的全局变量,在浏览器环境中输入Node.js)