Description
TypeScript Version: 3.7.2, Nightly
Search Terms: discriminated union, discriminant, excess property check, literal type, singleton type
Code
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, why no excess property check here?
errorMessage: "Error!" // no error, why no excess property check here?
}
Expected behavior:
After having set d1: "foo"
, TS should recognize that object literal testState
belongs to S1
and emit an error when trying to add excess properties isSuccess
and/or errorMessage
. There should be no other discriminant candidate than d1
, because only d1
exists in all three states.
Actual behavior:
There is no compile error.
Playground Link:
here
Related Issues:
Stackoverflow question
#32657 (maybe)
It kinda seems, isSuccess: boolean
is interpreted as a second discriminant candidate. You can also substitute isSuccess: true
/isSuccess: false
with isSuccess: 1
/isSuccess: 0
and neither get an error. An error is only raised, when isSuccess
is changed to a non-literal type like string
. But isSuccess
shouldn't be treated as discriminant in the first place!