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

Discriminated Unions with a common partially optional property #44689

Closed
nmalyschkin opened this issue Jun 22, 2021 · 3 comments
Closed

Discriminated Unions with a common partially optional property #44689

nmalyschkin opened this issue Jun 22, 2021 · 3 comments

Comments

@nmalyschkin
Copy link

Bug Report

πŸ”Ž Search Terms

Discriminated Unions with a common partially optional property

πŸ•— Version & Regression Information

  • I tried different versions of 3 and 4.

⏯ Playground Link

Playground link with relevant code

πŸ’» Code

interface B {
  a: true;
  b: number;
}
interface C {
  a?: false;
  c: number;
}
type Union = B | C;

const test1: Union = {
  a: false,
  c: 5,
};
const test2: Union = {
  c: 4,
};
const test3: Union = {
  a: true,
  b: 4,
};
const test4: Union = {
  b: 4,
  c: 4,
};

πŸ™ Actual behavior

test4 is displayed as valid.

πŸ™‚ Expected behavior

test4 should not be valid.

@MartinJohns
Copy link
Contributor

test4 is valid. All properties that must exist according to the interface are present, and no incompatible properties exist.

@whzx5byb
Copy link

whzx5byb commented Jun 22, 2021

It is unrelated to discriminated unions or optional property. A minimal repo:

interface B {
  b: number;
}
interface C {
  c: number;
}
type Union = B | C;

const test1: B = { b: 4, c: 4 }; // Error as expected, because of excess property check.
const test2: C = { b: 4, c: 4 }; // Error as expected, because of excess property check.
const test3: Union = { b: 4, c: 4 }; // No error.

See #20863
And this SO answer provides an workaround.

type UnionKeys<T> = T extends T ? keyof T : never;
type StrictUnionHelper<T, TAll> = T extends any ? T & Partial<Record<Exclude<UnionKeys<TAll>, keyof T>, undefined>> : never;
type StrictUnion<T> = StrictUnionHelper<T, T>

const test4: StrictUnion<B | C> = { b: 4, c: 4 }; // Error as expected.

@nmalyschkin
Copy link
Author

@whzx5byb
Thank you, that worked for me!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants