Closed
Description
There have been a lot of users who find it strange that this would compile:
declare function forEach<U>(array: U[], callback: (item: U) => void);
var strings: string[];
var callback: (item: {}) => void;
forEach(strings, callback); // U is inferred as {}
Suggestion: use the decorator @infer
to tell the compiler to infer a generic from that argument.
Example:
declare function forEach<U>(@infer<U> array: U[], callback: (item: U) => void);
var strings: string[];
var callback: (item: {}) => void;
forEach(strings, callback); // U is inferred as string (using only the decorated argument), thus this is an error
You can also add @infer
to multiple arguments, like this:
declare function forEachOnTwoArrays<U>(@infer<U> firstArray: U[], @infer<U> secondArray: U[], callback: (item: U) => void);
Adding @infer
to all parameters would have the same behavior as having no @infer
. Adding @infer
is optional, thus not a breaking change.
Rules for @infer
:
- You may only add type parameters of the direct containing function.
- You can add multiple type parameters like this:
@infer<T> @infer<U>
(or maybe@infer<T, U>
?) - Generics that are not referenced from an
@infer
decorator are inferred using the current behavior - Every generic
T
that is referenced from an@infer<T>
decorator is resolved using all parameters that are decorated with@infer<T>
of that function.
Note that this syntax is currently not supported, as the compiler expects (
after the generics. An alternative would be to write it as @infer<U>()
, but I think @infer<U>
is cleaner.