Closed
Description
TypeScript Version: master / 2.6.0-dev20170914 / whatever the playground has currently
I searched for immediate type guard
and type guard inference
, I hope I didn't miss an existing issue.
The issue is that the type inference fails for overloads with type guards such as the one for Array.filter when the type guard is passed as an immediate value. See also #7657 The problem seems to be that TS infers the type of the argument e
of the type guard from the type of the callback parameter of filter. In doing so, the return type of type guard is lost. If you specify the argument e
of the type guard explicitly, it works as expected.
Code
// for ref the Array signature.
interface Array<T> {
filter<S extends T>(callbackfn: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[];
}
declare const arr: (string | number)[]
// Property 'substring' does not exist on type 'string | number'.
arr.filter((e): e is string => 'string' == typeof e)[0].substring(0, 10);
arr.filter((e: any): e is string => 'string' == typeof e)[0].substring(0, 10); // ok
const isStringArrow = (e: any): e is string => 'string' == typeof e;
arr.filter(isStringArrow)[0].substring(0, 10); // ok
// Property 'substring' does not exist on type 'string | number'.
arr.filter(function (e): e is string { return 'string' == typeof e })[0].substring(0, 10);
// Property 'substring' does not exist on type 'string | number'.
arr.filter(function (e: any): e is string { return 'string' == typeof e })[0]
.substring(0, 10);
arr.filter(function (this: void, e: any): e is string { return 'string' == typeof e })[0]
.substring(0, 10); // ok
const isString = function (e: any): e is string { return 'string' == typeof e };
arr.filter(isString)[0].substring(0, 10); // ok
Expected behavior:
All cases should work.
Actual behavior:
See above.