3

So I have Array of generic object and want to iterate over the but typescript wont allow me. Here is some sample code. Any Suggestions of how this can be solved.

type someGeneric<T> = { item: T };

type stringGeneric = someGeneric<string>;

type numberGeneric = someGeneric<number>;

type someFunction = <T>(generic: someGeneric<T>) => T;

const someFunction: someFunction = (generic) => generic.item;

const stringGeneric: stringGeneric = { item: 'some String' },
    numberGeneric: numberGeneric = { item: 12 };

let genericArray = [stringGeneric, numberGeneric];
genericArray.forEach(generic => {
    someFunction(generic); // Error On This line.
});

You can just copy-paste the code to this link. I cant seem to share the code.

Amol Gupta
  • 2,054
  • 1
  • 14
  • 29

1 Answers1

4

The problem is that the function accepts a parameter of type someGeneric<T> if we try to pass in a parameter of type someGeneric<number> | someGeneric<string> typescript will not try to infer T from this it will just say the union is not compatible with the type someGeneric<T>

We can change the definition of the function so that the type parameter extends someGeneric<any>. This constraint will be compatible with the union. We can then use a conditional type to extract the item type from the T using a conditional type. Since conditional types distribute over unions the result of the extraction will be a union of the generic parameters to someGeneric<T>

type someGeneric<T> = { item: T };

type stringGeneric = someGeneric<string>;

type numberGeneric = someGeneric<number>;

type extractItemFromSomeGeneric<T extends someGeneric<any>> = T extends someGeneric<infer U> ? U : never;  
type someFunction = <T extends someGeneric<any>>(generic: T) => extractItemFromSomeGeneric<T>;

const someFunction: someFunction = (generic) => generic.item;

const stringGeneric: stringGeneric = { item: 'some String' },
    numberGeneric: numberGeneric = { item: 12 };

let someGeneric = [stringGeneric, numberGeneric];
someGeneric.forEach(generic => {
    someFunction(generic); // retruns string | number
});

Playground link

Titian Cernicova-Dragomir
  • 230,986
  • 31
  • 415
  • 357