Closed
Description
TypeScript Version: playground / 2.1.0-dev
Code
interface Foo {
bar: string;
}
interface CoolFoo extends Foo {
baz: string;
}
interface OtherFoo extends Foo {
zip: string;
}
type SomeFoo = CoolFoo | OtherFoo;
function run(foo: SomeFoo): number {
if ('baz' in foo) {
return foo.baz.length; // error
} else if ('zip' in foo) {
return foo.zip.length; // error
}
throw 'Wrong foo!';
}
Expected behavior:
Checking keys should be sufficient to check if foo
is either CoolFoo
or OtherFoo
.
In contrast checking by value works (at least in 2.1.0-dev, not playground):
interface Foo {
bar: string;
}
interface CoolFoo extends Foo {
type: 'cool';
baz: string;
}
interface OtherFoo extends Foo {
type: 'other';
zip: string;
}
type SomeFoo = CoolFoo | OtherFoo;
function run(foo: SomeFoo): number {
if (foo.type === 'cool') {
return foo.baz.length; // error
} else if (foo.type === 'other') {
return foo.zip.length; // error
}
throw 'Wrong foo!';
}
But even with 2.1.0-dev I cannot check for existence by value. This does not work:
function run(foo: SomeFoo): number {
if (foo.baz !== undefined) { // error
return foo.baz.length; // error
} else if (foo.zip !== undefined) { // error
return foo.zip.length; // error
}
throw 'Wrong foo!';
}
Not even that:
function run(foo: SomeFoo): number {
if (typeof foo.baz === 'string') { // error
return foo.baz.length; // error
} else if (typeof foo.zip === 'string') { // error
return foo.zip.length; // error
}
throw 'Wrong foo!';
}
Actual behavior:
Checking keys is not enough to check if foo
is either CoolFoo
or OtherFoo
. It doesn't compile, because TypeScripts treats foo
as CoolFoo | OtherFoo
even after checking keys.