简体   繁体   中英

How to infer all of the possible generic types in typescript

I have a function that accepts a record of Handler<I, O> and returns a function that returns the O of one of the handlers:

type Handler<I, O> = { i: I, o: O, handler: (i: I) => O };

function handlerGroup<I, O>(handlers: Record<string, Handler<I, O>>): (key: string) => O {
  return (key: string) => {
    const { i, handler } = handlers[key];
    return handler(i);
  }
}

For example:

const handleT1: Handler<number, number> = { i: 1, o: 1, handler: (i) => i }
const handleT2: Handler<number, string> = { i: 1, o: "1", handler: (i) => i.toString() }

handlerGroup({ T1: handleT1 }) //: (key: string) => number
handlerGroup({ T2: handleT2 }) //: (key: string) => string

But the problem starts when I try to add more than 1 record:

// Type 'Handler<number, string>' is not assignable to type 'Handler<number, number>'.
//   Types of property 'o' are incompatible.
//     Type 'string' is not assignable to type 'number'.(2322)
handlerGroup({ T1: handleT1, T2: handleT2 }) // expected: (key: string) => number | string

The problem is due to how I typed handleGroup , which I'm not entirely sure how to approach it.

So my question is, how can I let handleGroup infer all of the possible O based on the record?

See playground

I solved it by moving the handler itself as a generic, and then infer its O:

type Handler<I, O> = { i: I, o: O, handler: (i: I) => O };

type A<T> = T extends Record<string, Handler<any, infer U>> ? U : never;

function handlerGroup<H extends Record<string, Handler<any, any>>>(handlers: H): (key: string) => A<typeof handlers> {
  return (key: string) => {
    const { i, handler } = handlers[key];
    return handler(i);
  }
}

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