4

Given is a discriminated union type S1 | S2 | S3:

type S1 = { d1: "foo"; }
type S2 = { d1: "bar"; isSuccess: true; }
type S3 = { d1: "baz"; isSuccess: false; errorMessage: string; }

type State = S1 | S2 | S3;

const testState: State = {
  d1: "foo",
  isSuccess: true, // no error, urgh.. 
  errorMessage: "Error!" // no error, urgh.. 
  // why no excess property check here?
}

I would expect TS to choose discriminant d1, as it is the only property that exists in all three states and is a valid singleton type candidate. isSuccess can't be chosen here, because it does not exist in S1.

Assuming this behavior, why aren't excess property checks respected and no error emitted, as soon as I type isSuccess: true, given d1 has value "foo"?

Here is a test sample I made to understand the problem.

bela53
  • 3,040
  • 12
  • 27
  • 2
    Does this answer your question? [TypeScript a | b allows combination of both](https://stackoverflow.com/questions/46370222/typescript-a-b-allows-combination-of-both) (It also came up recently as https://stackoverflow.com/q/59462318/1426891.) – Jeff Bowman Dec 27 '19 at 22:20
  • What's weird is that `State` has to specify all three types before no error is displayed. If it's `S1 | S2` or `S1 | S3` or `S2 | S3`, you get the errors as expected. Also, changing `S3`'s `isSuccess` to `true` preserves the errors. It's when `isSuccess` is a `boolean` rather than `true` that errors stop occurring. – dx_over_dt Dec 28 '19 at 00:24
  • This actually looks like a compiler bug to me. Adding `as S1`, `as S2`, and `as S3` to the end of your `testState` declaration shows that you only don't get the error when it's interpreting your object as an `S1`. If it knows it's an `S1`, then it should know what properties are and aren't allowed. – dx_over_dt Dec 28 '19 at 00:30
  • 1
    @JeffBowmansupportsMonica No, this is not a duplicate. In your mentioned posts, no valid discriminated union types were used. For example, in `{ value: number, data: string } | { value2: number, note: string };` `number` and `string` are no valid singleton types. But I used string literal types `"foo" | "bar" | "baz"` for prop `d1` here, which can act as a discriminant. You can find more infos [here](https://github.com/microsoft/TypeScript/pull/9163) and [here](https://github.com/microsoft/TypeScript/pull/27695). Please reopen the question. – bela53 Dec 28 '19 at 10:09
  • @dx_over_dt indeed! For me it seems buggish, too. – bela53 Dec 28 '19 at 10:20
  • 1
    Created issue: https://github.com/microsoft/TypeScript/issues/35890 – bela53 Dec 28 '19 at 11:52
  • Voted to reopen, but it may be helpful here (and in the future) to edit in links to similar questions in your question and identify ways in which your question is distinct. – Jeff Bowman Dec 29 '19 at 18:06

0 Answers0