Skip to content

Type inference fails with immediate type guards #18562

Closed
@NaridaL

Description

@NaridaL

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

playground

Expected behavior:
All cases should work.
Actual behavior:
See above.

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already created

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions