question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. ItΒ collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Union not narrowed with `typeof x.y` as a discriminant

See original GitHub issue

TypeScript Version: 3.6.0-dev.20190713

Search Terms: TS2339, union type object, union type property does not exist And github suggestions while I was writing the title.

Code

type Test = {
    someKey: false
} | {
    someKey: {
        someKeyInside?: number
    },
    someKeyThatExistOnlyIfOtherKeyIsNotFalse: string;
};

declare const test: Test;

if (typeof test.someKey === 'object') {
    console.log(test.someKeyThatExistOnlyIfOtherKeyIsNotFalse);
}

Expected behavior: String in someKeyThatExistOnlyIfOtherKeyIsNotFalse should be logged

Actual behavior:

error TS2339: Property 'someKeyThatExistOnlyIfSomeKeyIsNotFalse' does not exist on type 'Test2'.
  Property 'someKeyThatExistOnlyIfSomeKeyIsNotFalse' does not exist on type '{ someKey: false; }'.

29     console.log(test2.someKeyThatExistOnlyIfSomeKeyIsNotFalse); // TS2339: Property 'someKeyThatExistOnlyIfSomeKeyIsNotFalse' does not exist on type '{ someKey: false; }'.

Playground Link: https://www.typescriptlang.org/play/index.html#code/C4TwDgpgBAKhDOwCMUC8UDeAoKurwHsBbCAaQhAC4oAzAQwBt4IsBfKAH0xz0JPKrc8w-MTIUAkgDt4ASwAmEalICuRAEYQATj1ysANLtH8KMABZ1gAUQAesxAHkpDEBJoPgZ7QInwAcgTAAGKMzNSIWrJSAOYA3GzxWIoAxgx0WtDJBDLAUMAIyNRwiEiJsjRQABT5JQB0fOIgAJRCeFkyBAwQtQwE0dUFSPViAuaWtvbATi5uHl5aPv6BIUwQTbFQAPSbUA6kAIRsWFigkLAFAExorbgNAtT0q2ycN8aN1NgieNuwXlDZLn+Umg8nKNG0ECkyWgNC0xDy4GgxWQ+jePhkCkydCkUE0UBUUkUNCiEHkQLRFCMwjukgxigA-Mo1JodMIDEYaSAxtY7I5nK53J5vJIlsFQkp8MBIjF4qxEik0hkoO1EHlLkVLmUKtVEQQKjVgBdhiYQGhUOgAOQEdQAKwgyWAFpanza2UIXR6fQGiCNnO5Ez5M0F80WATFq3WWx2MAAyhcAMzxgCc1AACnDIFpQFALX6LDzJtMBXNha5RStmBaoPICAgoFJAlAILzctkEWcLRgKYJHswNqwLbU2EA

Take a look at type Test1. The only one difference from type Test2 is someKeyInside should be always defined.

Related Issues:

Issue Analytics

  • State:open
  • Created 4 years ago
  • Reactions:6
  • Comments:9 (4 by maintainers)

github_iconTop GitHub Comments

3reactions
bterlsoncommented, Jan 31, 2020

Just chiming in to say I would love this fixed! Our repro is something like the following:

interface A { x: string, y: string };
interface B { x: number, y: number };
type X = A | B;
 
declare var bar: X;
 
if (typeof bar.x === 'string') {
    let y = bar.y; // string | number, but really should be string.
}

Essentially we have some methods we’d like to return union of object types from. The object types are mostly distinct with a little overlap. Ideally users would just check the field that they want is present, and TS would do the math and present a proper type inside the if block.

We ran in to this because we were using a tagged union pattern which was working fine, but then attempted to generalize it, and found the narrowing stopped working.

1reaction
jack-williamscommented, Jul 18, 2019

I’m not sure typeof has ever triggered narrowing by discriminant.

Read more comments on GitHub >

github_iconTop Results From Across the Web

typescript - Why doesn't 'typeof' narrow a union type when the ...
Typescript discriminated unions (currently) only support property values as discriminants, not property types.
Read more >
Documentation - Advanced Types - TypeScript
Union types are useful for modeling situations when values can overlap in the types ... the type of the function's prototype property if...
Read more >
Understanding the discriminated union pattern
The discriminated union pattern is a way of narrowing a union type. A requirement for this pattern is for the types in the...
Read more >
Advanced Types - TypeScript - JavaScript that scales.
instanceof type guards are a way of narrowing types using their constructor function. ... Discriminated unions are useful in functional programming.
Read more >
Discriminated Unions - F# | Microsoft Learn
As with a union type in C++ or a variant type in Visual Basic, the data stored in the value is not fixed;...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found