Skip to content

fix(.exhaustive): optional discriminant#319

Merged
gvergnaud merged 4 commits intomainfrom
gvergnaud/fix-exhaustive-on-optional-properties
May 18, 2025
Merged

fix(.exhaustive): optional discriminant#319
gvergnaud merged 4 commits intomainfrom
gvergnaud/fix-exhaustive-on-optional-properties

Conversation

@gvergnaud
Copy link
Owner

@gvergnaud gvergnaud commented May 11, 2025

This PR fixes #278

This new release fixes the following bug in exhaustiveness checking when matching on optional properties:

type Input = { type?: 'one' } | { type: 'two' };

const f1 = (input: Input) =>
  match(input)
    .with({ type: 'one' }, () => {})
    .with({ type: 'two' }, () => {})
    .exhaustive(); // shouldn't type-check, but does 👎


const f2 = (input: Input) =>
  match(input)
    .with({ type: 'one' }, () => {})
    .with({ type: 'two' }, () => {})
    .with({ type: undefined }, () => {}) // <- the type key needs to be present.
    .exhaustive();  // shouldn't type-check, but does 👎

These two cases don't type check anymore. They fail with a NonExhaustiveError<{ type?: undefined; }>. To fix it, you should do:

type Input = { type?: 'one' } | { type: 'two' };

const f = (input: Input) =>
  match(input)
    .with({ type: 'one' }, () => {})
    .with({ type: 'two' }, () => {})
    .with({ type: P.optional(undefined) }, () => {}) // <- the type property may not be there
    .exhaustive(); // ✅

This is a purely type-level change, the runtime behavior is still the same.

@gvergnaud gvergnaud changed the title Gvergnaud/fix exhaustive on optional properties fix(.exhaustive): optional discriminant May 11, 2025
@gvergnaud gvergnaud force-pushed the gvergnaud/fix-exhaustive-on-optional-properties branch from efa8449 to a77e69a Compare May 11, 2025 20:48
@gvergnaud gvergnaud marked this pull request as ready for review May 18, 2025 13:43
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

Successfully merging this pull request may close these issues.

Exhaustiveness check fails for tagged union with a partial discriminant.

1 participant