-
Notifications
You must be signed in to change notification settings - Fork 12.9k
Closed
Labels
BugA bug in TypeScriptA bug in TypeScriptFix AvailableA PR has been opened for this issueA PR has been opened for this issue
Milestone
Description
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:
Related Issues:
Metadata
Metadata
Assignees
Labels
BugA bug in TypeScriptA bug in TypeScriptFix AvailableA PR has been opened for this issueA PR has been opened for this issue