Home > OS >  Why is my typing failing when array contains multiple elements but not only one?
Why is my typing failing when array contains multiple elements but not only one?

Time:09-01

Given the following code:

function SumSystem() {
    return {
        sum(x: number, y: number) {
            return x   y
        }
    }
}

function MultiplySystem() {
    return {
        multiply(x: number, y: number) {
            return x * y
        }
    }
}

function emit<S extends () => Record<string, unknown>>(systems: S[]): { [K in keyof ReturnType<S>]: ReturnType<S>[K] } {
    // whatever
    return {}
}

emit([SumSystem]).sum(1, 2) // works
emit([MultiplySystem]).multiply(2, 2) // works

emit([SumSystem, MultiplySystem]).sum(1, 2) // does not work
emit([SumSystem, MultiplySystem]).multiply(2, 2) // does not work

As per comments, the last two emits are not working, and that's occurring because I am passing two values into the argument's array: [SumSystem, MultiplySystem].

Questions:

  1. What's the problem?
  2. Is it possible to fix it?
  3. If the second question is true, how?

Playground

CodePudding user response:

Use the generic to infer the type of the entire array instead, get the return type of all the functions, then turn that union into an intersection for the result.

type UnionToIntersection<U> = 
  (U extends any ? (k: U) => void : never) extends ((k: infer I)=>void) ? I : never

function emit<S extends (() => Record<string, unknown>)[]>(systems: S): UnionToIntersection<ReturnType<S[number]>> { ... }

Playground


Your solution does not work as intended because S is inferred as (() => { sum... }) | (() => { multiply... }) instead of an array.

  • Related