打字稿使用函数中的第一个参数从接口查找第二个参数的类型

Typescript look up the type of the second argument from interface using first argument in a function

是否可以让 Typescript 根据接口确定此回调的参数类型?

export interface MiddlewareEvent {
    onNewAccount: (accountId: string, timestamp: number) => void,
    onAccountDelete: (accountId:string, timestamp:number)=>void,
}

 const middlewareMap: Map<keyof MiddlewareEvent,((...arg: any) => void )[]> = new Map();

function registerMiddleWare(
    eventId: keyof MiddlewareEvent,
    middleware: ((...arg: any) => void)
) {
        const existing = middlewareMap.get(eventId);
        if (!existing?.length) {
            middlewareMap.set(eventId, [middleware]);
        } else {
            existing.push(middleware);
        }
}

registerMiddleWare(`onNewAccount`, (accountId: number, datetime: string) => {
    console.log(`Wait, Typescript should have prevented this`)
    console.log(`account Id is string not number`)
    console.log(`datetime has been changed to timestamp and is now a number`)
})

想法是将接口的 属性 作为字符串(或枚举?)作为第一个参数传递给函数,Typescript 应该弄清楚回调参数的类型是通过在界面中查看该键来获取第二个参数。

这不会要求用户每次都手动传递泛型类型参数。

当然,您只需要一个推断的泛型函数。让它推断传入的 eventId,然后根据该键钻取 MiddlewareEvent

function registerMiddleWare<EventName extends keyof MiddlewareEvent>(
    eventId: EventName,
    middleware: MiddlewareEvent[EventName]
) { /* ... */ }

registerMiddleWare(`onNewAccount`, (accountId: number, datetime: string) => {})
// Argument of type
//   '(accountId: number, datetime: string) => void'
// is not assignable to parameter of type
//   '(accountId: string, timestamp: number) => void'

Playground