Description
TypeScript Version: 2.4.0
Code
// The following works no problem
type ExhaustiveType = Array<number | undefined>;
const test1 = (value: ExhaustiveType) => value.filter(v => v === 2);
/** Cannot invoke an expression whose type lacks a call signature. Type '{ (callbackfn: (this: void, value: number | undefined, index: number, array: (number | undefined)...' has no compatible call signatures. */
type ExcessiveType = number[] | Array<number | undefined>;
const test2 = (value: ExcessiveType) => value.filter(v => v === 2);
Expected behavior:
Both examples compile.
Actual behavior:
The latter example fails with Cannot invoke an expression whose type lacks a call signature. Type '{ (callbackfn: (this: void, value: number | undefined, index: number, array: (number | undefined)...' has no compatible call signatures.
Explanation
ExhaustiveType
and ExcessiveType
both represent exactly the same types. The latter is more explicit, and while in this particular example it might look silly, w/ more complex types and type aliases, being more explicit allows for more expressivity. IMHO TypeScript could at the time of defining ExcessiveType
, 'reduce it down' to the ExhaustiveType
. Alternatively (to preserve expressiveness e.g. in the IDE), the compiler could internally treat them as equivalent.