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

Union type not act as mutual exclusion #31055

Closed
k8w opened this issue Apr 22, 2019 · 10 comments
Closed

Union type not act as mutual exclusion #31055

k8w opened this issue Apr 22, 2019 · 10 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@k8w
Copy link

k8w commented Apr 22, 2019

TypeScript Version: 3.4.3

Search Terms:
union mutual exclusion

Code

type A = { A: string };
type B = { B: string };
let ab: A | B = {
    A: 'xxxxxxxxx',
    B: 123
}

Expected behavior:
Compiled error.
ab should be a mutual exclusion between A and B.

  1. there should be only 1 field: A or B, shouldn't have 2 fields at the same time.
  2. type of field B is wrong

Actual behavior:
Compiled succ.

Playground Link:

Related Issues:

@MartinJohns
Copy link
Contributor

I'd expect a EPC error (excess property checks) as well. But besides that your object literal fulfills the contract of type A and of type B, so the assignment is valid.

Playground link: https://typescript-play.js.org/#code/...

Related Issues: #12936 and #12936 (comment) and #14094.

@jack-williams
Copy link
Collaborator

jack-williams commented Apr 22, 2019

The issue tracking this particular problem is #20863 --- there is no discriminant property for the union type.

@RyanCavanaugh RyanCavanaugh added the Working as Intended The behavior described is the intended behavior; this is not a bug label Apr 22, 2019
@RyanCavanaugh
Copy link
Member

Union types are not intended to be automatically mutually exclusive

@k8w
Copy link
Author

k8w commented Apr 23, 2019

@RyanCavanaugh ab.B === 123 is also working as intended?
Neither type A nor type B define property B could be a number

@RyanCavanaugh
Copy link
Member

For an assignment S to T | U, the assignment is valid if S is a valid assignment to either type. { A: string, B: number } is a valid { A: string }, therefore the assignment is valid.

@k8w
Copy link
Author

k8w commented Apr 23, 2019

@RyanCavanaugh
{ B: number } never defined in A and B.

So can I understand this as:

  • If: part of S is valid to A or B
  • Then: S is valid to A|B,

But why {A: 'XXXXX', C: 12345} is not valid?

@RyanCavanaugh
Copy link
Member

The things that excess property checking warns about aren't things related to subtyping or assignability.

@AlCalzone
Copy link
Contributor

AlCalzone commented Apr 25, 2019

@RyanCavanaugh is it intended for VSCode intellisense to provide auto completion for B if A is already declared in an object literal?
I would guess not, but I stumbled across this today:
grafik
In my understanding the intent is pretty clear that bar is either supposed to be called with {a: string} or {b: number}, not both. While it is legal to do so, I would expect intellisense to not propose b as an auto completion entry here.

@typescript-bot
Copy link
Collaborator

This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

@EduardoRFS
Copy link

EduardoRFS commented Aug 5, 2019

@RyanCavanaugh it doesn't make any sense, code above, because it doesn't fulfill A, neither does it fulfill B, it only fulfill A & B, union isn't exclusively but it should fulfill at least one of them, in this case it doesn't fulfill anyone of them.

type A = { a: string };
type B = { b: string };
type T = A | B;

// error: Object literal may only specify known properties
const a: A = {
    a: 'xxxxxxxxx',
    b: 'yyyy'
};
// error: Object literal may only specify known properties
const b: B = {
    a: 'xxxxxxxxx',
    b: 'yyyy'
};
// what?
const t: T = {
    a: 'xxxxxxxxx',
    b: 'yyyy'
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
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

7 participants