I think typeof undefined checks should not error in the last accessor of the expression. Because I'm already checking for undefined:
So below code should be perfectly fine:
interface A {
a: string;
}
interface B {
b: string;
}
function isA(x: A |聽B): x is A {
return typeof x.a !== 'undefined'; // Error in "a" does not exists
}
Right now, I have to type assert x to any.
(You forgot to quote undefined, right now that check is _always_ false)
This is a consequence of | types only allowing access to the subset of common known keys, because something that matches A is also allowed to coincidentally have a key that would have matched B, and vice-versa.
If you add b: never to A and a: never to B, this will allow you to test them for refinement even without needing an assertion function.
This is a suggestion to allow non-existing accessors to be allowed just in typeof undefined checks.
Without exact types (#12936) this is unsound.
interface A {
a: string;
}
interface B {
b: string;
}
function isA(x: A | B): x is A {
return typeof (x as any).a !== 'undefined';
}
function f(value: A | B): string {
return isA(value) ? value.a.toUpperCase() : value.b.toLowerCase();
}
// Crashes on `1.toUpperCase()`
console.log(f({ a: 1, b: "" }));
Even though it is unsound, my suggestion is still to allow one to write:
typeof x.a !== 'undefined';
Instead of having to:
typeof (x as any).a !== 'undefined';
And this should only work on typeof undefined checks. Because you are checking undefined on runtime and the compiler shouldn't complain about a non-existent property.
Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.