Skip to content

Narrowing discriminated unions with user-defined type guards #11787

Closed
@timruffles

Description

@timruffles

TypeScript Version: 2.0.3

Code

type Cheese = {
  type: 'brie';
  brieOnly: true,
} | {
   type: 'cheddar';
  cheddarOnly: true,
}


function narrows<Wide extends string, Narrow extends Wide>(w: Wide, n: Narrow): w is Narrow {
    return w === n;
}


function doSomethingWithCheese(cheeseSample: Cheese) {
    if (cheeseSample.type === 'cheddar') {
        cheeseSample.cheddarOnly // ok
    }

    if (narrows(cheeseSample.type, 'cheddar')) {
        const t: 'cheddar' = cheeseSample.type; // has narrowed 
        cheeseSample.cheddarOnly // not ok, didn't narrow discriminated union
    }
}

Expected behavior:

Discriminated unions would work with type-guards in this way.

Actual behavior:

It doesn't, and I have to write a load of stuff like this in unit-tests:

    if (cheese.type === 'cheddar') {
          assert(/* some assertions using cheddar specific properties */);
    } else {
           throw Error("wrong type of cheese");
        }

rather than doing it in one step with an assertion throwing version of narrows:

    if (assert.narrows(cheese.type, 'cheddar')) {
          assert(/* some assertions using cheddar specific properties */);
    }

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