Skip to content

Generics extending unions cannot be narrowed #13995

Closed
@krryan

Description

@krryan

TypeScript Version: 2.2.0-dev.20170126

Code

declare function takeA(val: 'A'): void;
export function bounceAndTakeIfA<AB extends 'A' | 'B'>(value: AB): AB {
    if (value === 'A') {
        takeA(value);
        return value;
    }
    else {
        return value;
    }
}

Expected behavior:
Compiles without error.

Actual behavior:

Argument of type 'AB' is not assignable to parameter of type '"A"'.

It works correctly if I just use value: 'A' | 'B' as the argument to bounceAndTakeIfA, but since I want the return value to type-match the input, I need to use the generic (overloading could do it, but overloading is brittle and error-prone, since there is no error-checking that the overload signatures are actually correct; my team has banned them for that reason). But (I'm guessing) since AB extends 'A' | 'B', narrowing doesn't happen. In reality, I am just using extends to mean AB ⊂ 'A' | 'B', but extends can mean more than that, which (I suspect) is why TS is refusing to narrow on it.

Some alternative to extends that more specifically means ⊂ (subsets maybe?) would probably be the best solution here?

Metadata

Metadata

Assignees

Labels

Fix AvailableA PR has been opened for this issueIn DiscussionNot yet reached consensusSuggestionAn idea for TypeScript

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions