Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't access potential member on union type #18750

Closed
testerez opened this issue Sep 25, 2017 · 4 comments
Closed

Can't access potential member on union type #18750

testerez opened this issue Sep 25, 2017 · 4 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@testerez
Copy link

testerez commented Sep 25, 2017

TypeScript Version: 2.4.0 / nightly (2.5.0-dev.201xxxxx)

Code

interface Foo {
  foo: string;
}

interface Bar {
  bar: string;
}

function test(item: Foo | Bar) {
  console.log(item.foo || item.bar)
}

Expected behavior:
This pattern is very common in javascript, that would be great to make it valid in typescript.

Actual behavior:

Property 'foo' does not exist on type 'Foo | Bar'.
  Property 'foo' does not exist on type 'Bar'.
Property 'bar' does not exist on type 'Foo | Bar'.
  Property 'bar' does not exist on type 'Foo'.
@RyanCavanaugh RyanCavanaugh added the Working as Intended The behavior described is the intended behavior; this is not a bug label Sep 25, 2017
@kitsonk
Copy link
Contributor

kitsonk commented Sep 25, 2017

That would make the type system unsound. Doing so would cause all sorts of bad code.

You need to understand better how the typing system works. When you have a Schrödinger's cat type like that, TypeScript will only allow you to access the properties it knows are in common. If you wanted it to work, you could change the type:

interface Foo {
  foo: string;
}

interface Bar {
  bar: string;
}

function test(item: Foo & Bar) {
  console.log(item.foo || item.bar)
}

But it depends on what you are trying to do and represent properly, because you could narrow the type as well:

interface Foo {
  foo: string;
}

interface Bar {
  bar: string;
}

function isFoo(value: any): value is Foo {
  return 'foo' in value;
}

function test(item: Foo | Bar) {
  console.log(isFoo(item) ? item.foo : item.bar)
}

@RyanCavanaugh
Copy link
Member

This has been the behavior forever and is not a bug. See #805

@testerez
Copy link
Author

But what about stating that type of (Foo | Bar).foo is string | undefined. It seams pretty reasonable no?

@kitsonk
Copy link
Contributor

kitsonk commented Sep 25, 2017

No.

If you want Bar to possibly have foo then you can write it that way.

interface Bar {
  bar: string;
  foo?: string;
}

The typing system is designed to be sound. It isn't designed to be abused.

@microsoft microsoft locked and limited conversation to collaborators Jun 14, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

3 participants