Skip to content

Check keys in code flow analysis #10515

Closed
@donaldpipowitch

Description

@donaldpipowitch

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already created

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions