Skip to content

Narrowing a type union with user-defined type guard #12235

@lukaw3d

Description

@lukaw3d

TypeScript Version: >= 2.0.2

Code

getResults1([]);
getResults1({data: []});

getResults2([]);
getResults2({data: []});


type Result = {value: string}
type Results = Result[];


function isResponseInData<T>(value: T | { data: T}): value is { data: T } {
    return value.hasOwnProperty('data');
}
function getResults1(value: Results | { data: Results }): Results {
    // error TS2322: Type 'Results | {data: Results}' is not assignable to 'Results'
    return isResponseInData(value) ? value.data  // value: {data: Results}
                                   : value;      // value: Results | {data: Results}   !!
}


function isPlainResponse<T>(value: T | { data: T}): value is T {
    return !value.hasOwnProperty('data');
}
function getResults2(value: Results | { data: Results }): Results {
    // Good
    return isPlainResponse(value) ? value        // value: Results
                                  : value.data;  // value: {data: Results}
}

Expected behavior:
Expected both getResults1 and getResults2 to compile fine, as they did in typescript@2.0.0 and typescript@1.8.10.

Actual behavior:
getResults1 doesn't compile, because value's type doesn't get narrowed in versions from typescript@2.0.2 forward (still an issue in 2.2.0-dev.20161114).

Metadata

Metadata

Assignees

Labels

BugA bug in TypeScriptFixedA PR has been merged for this issue

Type

No type
No fields configured for issues without a type.

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions