Skip to content

Discriminate union inference inconsistent behavior with if/else checks #36777

@dannycochran

Description

@dannycochran

TypeScript Version:

Confirmed in:

3.7.5
3.9.x-dev.20200212 (playground as of 2/13/2020)

Search Terms:

discriminate union, if else, switch statement, object lookup

Code

type TestA = {
  type: 'testA';
  bananas: 3;
};

type TestB = {
  type: 'testB';
  apples: 5;
};

type AllTests = TestA | TestB;

type MapOfAllTests = Record<string, AllTests>;

const doTestingStuff = (mapOfTests: MapOfAllTests, ids: string[]) => {
  ids.forEach(id => {
    // if we type this as "AllTests" instead of leaving it non-typed, the compiler warning
    // below also disappears..!?
    let test;
    test = mapOfTests[id];

    // at this point, TS considers "test" to be "AllTests",
    // so, discriminate union tests should work..?
    if (test.type === 'testA') {
      //  Property 'bananas' does not exist on type 'AllTests'.
      //    - Property 'bananas' does not exist on type 'TestB'.
      console.log(test.bananas);
    }
    switch (test.type) {
      case 'testA': {
       // no compiler warning
        console.log(test.bananas);
      }
    }
  });
};

Expected behavior:

I'm not entirely sure what the right behavior is. At the point of the discriminate union if/else check, TypeScript considers test to be AllTests. So, I would imagine that it should work as it does in he switch case. But maybe the actual issue is that I don't explicitly define what item is in the beginning?

Actual behavior:

In the if/else check for (test.type === 'testA'), test.bananas has a compiler warning complaining that bananas may not exist on TypeB.

Playground Link:

http://www.typescriptlang.org/play/?ts=3.9.0-dev.20200212&ssl=1&ssc=1&pln=34&pc=1#code/C4TwDgpgBAKhDOwCCUC8UDeAoKVSQC4oByYBZYgbhygCMBDAOyfviIGZqBfarfaOIgBCaTDX5FS5IVRr0wYADYIiAVm69+UJIsWDg8UfpQAfWNM3hoAWXkB5AGY695Q+gBKEAMYB7AE4AJgA8iH4AlowA5gA02rr68AB8vL6MiFABPvoRkQDKwACuDg6iABQAtvYOCUS2YI7OCbFhAWxQoTkA2gC6AJRoiWK4LfAAdA7+AKL0XgAWpS0DQ7hQAPSrUGElAO7QWsCzYYasUABEja6nm2lk9AFQPiXK9ABuOZvAUIw+jAC0-AFYgdoL5ymAwso-FBtvQ-IwcjRcOs6BBFD5tlB6Ip4D4Mkd5JBYWNRgBCAD8iKgyk+ZEQ1BWeHIokq9Wqrk6LW6vAZyPoNMOhjAPgiwFiMFyUFS8BaED8hlOtOAV2AuNo0HO8Uu0UpyJxsQCRy84XKET50AK8J+jMQhngsx8BUU922-gA1qNRhSGVsoKVFaMtKggyRFUhiP1sAzcFKfMpRmjIn7yKMGMxmPBevSVlxKfBtmFgHNff7+BHKdHWNApIgw0RI1Hoz8cXGE0nECmWOnM+WoDmGX3e92eFggA

Related Issues:

Metadata

Metadata

Assignees

Labels

BugA bug in TypeScriptFix AvailableA PR has been opened 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