简体   繁体   中英

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

Is it possible to make Typescript figure out the types of the arguments of this callback based on an interface?

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`)
})

The idea is to just pass the property of the interface as a string (or enum? ) to a function as first parameter and Typescript should figure out of the types of the argument of the callback which is the second parameter by looking that key in the interface.

This won`t require the user to manually pass a generic type argument everytime.

Sure, you just need an inferred generic function. Let it infer the eventId being passed in, and then drill into MiddlewareEvent based on that key.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM