Typescript: Union type not act as mutual exclusion

Created on 22 Apr 2019  路  10Comments  路  Source: microsoft/TypeScript


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:

Working as Intended

Most helpful comment

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 https://github.com/Microsoft/TypeScript/issues/12936#issuecomment-284590083 and #14094.

All 10 comments

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 https://github.com/Microsoft/TypeScript/issues/12936#issuecomment-284590083 and #14094.

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

Union types are not intended to be automatically mutually exclusive

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

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.

@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?

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

@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.

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

@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'
};
Was this page helpful?
0 / 5 - 0 ratings