Skip to content

Narrowing discriminated unions with user-defined type guards #11787

@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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions