thorn thorn - 8 months ago 37
TypeScript Question

Why isn't the type argument inferred as a union type?

This code

declare function fn<T, U>(array: T[], predicates: ((arg: T) => U)[]): [T, U];
let a = fn([1, 2, 3], [x => 2, x => 's']);

leads to this error:

The type argument for type parameter 'U' cannot be inferred from the
usage. Consider specifying the type arguments explicitly. Type
argument candidate 'number' is not a valid type argument because it is
not a supertype of candidate 'string'. function fn(array: T[],
predicates: ((arg: T) => U)[]): [T, U]

Why can't be
simply inferred to have the type
string | number


TypeScript in general will not synthesize a union type during generic inference. The reason, in simplified terms, is that it's not desirable to do inference like this:

function compare<T>(x: T, y: T): number { ... }
// Could infer T: string | number here... but that'd be bad
compare('oops', 42);

If a generic type can't be formed by picking one of the inference candidates, you'll get the error you posted.

Experience informed this choice. In prior versions (before union types existed), {} would be inferred if no inference candidate was a supertype of all candidates. In practice this led to a lot of missed errors that looked like the example above.