Skip to content

fix(eslint): replace untyped default-case and consistent-return with typed switch-exhaustiveness-check#109743

Merged
JoshuaKGoldberg merged 1 commit into
masterfrom
tseslint-switch-exhaustiveness-check
Mar 31, 2026
Merged

fix(eslint): replace untyped default-case and consistent-return with typed switch-exhaustiveness-check#109743
JoshuaKGoldberg merged 1 commit into
masterfrom
tseslint-switch-exhaustiveness-check

Conversation

@JoshuaKGoldberg

@JoshuaKGoldberg JoshuaKGoldberg commented Mar 2, 2026

Copy link
Copy Markdown
Member

Following up on #109725 (comment): our lint rules that attempt to enforce exhaustive logical handling aren't set up right. We're using ESLint's core rules that are not type-aware and so are actually buggy / problematic:

  • consistent-return: Requires return statements to either always or never specify values. This can be thought of as a safety point (never accidentally implicitly returning undefined) or a stylistic point (clearly indicating returned values). TypeScript handles the safety point.
  • default-case: Requires default cases in switch statements. This doesn't factor in type information for union types, resulting in a need to add a default even if the switch is already exhaustive or (e.g. for finite unions) or cannot be (e.g. for primitive types).

This PR switches from them to the type-aware @typescript-eslint/switch-exhaustiveness-check. That rule knows to only enforce asking for handling all cases when the switch is over a union type.

In other words, for a switch (value), if a value is...

  • string: nothing will require a default:
  • "a" | "b": then if there isn't both case "a": and case "b":, there will need to be default:

@github-actions github-actions Bot added the Scope: Frontend Automatically applied to PRs that change frontend components label Mar 2, 2026
@JoshuaKGoldberg JoshuaKGoldberg changed the title ref(eslint): replace untyped default-case and consistent-return with typed switch-exhaustiveness-check chore(eslint): replace untyped default-case and consistent-return with typed switch-exhaustiveness-check Mar 2, 2026
case AST_NODE_TYPES.JSXNamespacedName:
return `${node.namespace.name}:${node.name.name}`;
default:
return node.name;

@JoshuaKGoldberg JoshuaKGoldberg Mar 2, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is from the original conversation in #109725 (comment). I'd used default: instead of the more specific AST_NODE_TYPES.JSXIdentifier to appease the two lint rules.

@JoshuaKGoldberg JoshuaKGoldberg changed the title chore(eslint): replace untyped default-case and consistent-return with typed switch-exhaustiveness-check [Reference] chore(eslint): replace untyped default-case and consistent-return with typed switch-exhaustiveness-check Mar 10, 2026
@JoshuaKGoldberg JoshuaKGoldberg force-pushed the tseslint-switch-exhaustiveness-check branch from 3511c2a to 29fc1de Compare March 26, 2026 17:59
@JoshuaKGoldberg JoshuaKGoldberg force-pushed the tseslint-switch-exhaustiveness-check branch 2 times, most recently from a8f8a52 to 9711d83 Compare March 26, 2026 20:14
Comment thread eslint.config.ts
'@typescript-eslint/no-unnecessary-type-assertion': 'error',
'@typescript-eslint/switch-exhaustiveness-check': [
'error',
{considerDefaultExhaustiveForUnions: true},

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

considerDefaultExhaustiveForUnions is the juice that makes the lint rule behave like I think Sentry wants. tl;dr: it tells the rule that a default: case should make a switch statement be considered an exhaustive switch over a union. Otherwise, we'd have to have a case for every constituent (possible type).

@JoshuaKGoldberg JoshuaKGoldberg marked this pull request as ready for review March 26, 2026 20:25
@JoshuaKGoldberg JoshuaKGoldberg requested review from a team as code owners March 26, 2026 20:25
@JoshuaKGoldberg JoshuaKGoldberg removed request for a team March 26, 2026 20:25
@JoshuaKGoldberg JoshuaKGoldberg removed request for a team March 26, 2026 20:25

@natemoo-re natemoo-re left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Diff looks good!

One thing to note is that enableTypeAwareLinting is only set in CI because we've had major performance problems which makes it unsuitable for running in precommit. As long as you're not concerned that this rule moves over, I'm not!

@JoshuaKGoldberg JoshuaKGoldberg changed the title [Reference] chore(eslint): replace untyped default-case and consistent-return with typed switch-exhaustiveness-check chore(eslint): replace untyped default-case and consistent-return with typed switch-exhaustiveness-check Mar 26, 2026

@TkDodo TkDodo left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔥

…typed switch-exhaustiveness-check

Made-with: Cursor
@JoshuaKGoldberg JoshuaKGoldberg force-pushed the tseslint-switch-exhaustiveness-check branch from 9711d83 to 9d4b27c Compare March 31, 2026 12:59
@JoshuaKGoldberg JoshuaKGoldberg changed the title chore(eslint): replace untyped default-case and consistent-return with typed switch-exhaustiveness-check fixed(eslint): replace untyped default-case and consistent-return with typed switch-exhaustiveness-check Mar 31, 2026
@JoshuaKGoldberg JoshuaKGoldberg changed the title fixed(eslint): replace untyped default-case and consistent-return with typed switch-exhaustiveness-check fix(eslint): replace untyped default-case and consistent-return with typed switch-exhaustiveness-check Mar 31, 2026
@JoshuaKGoldberg JoshuaKGoldberg merged commit 6abcd1c into master Mar 31, 2026
73 checks passed
@JoshuaKGoldberg JoshuaKGoldberg deleted the tseslint-switch-exhaustiveness-check branch March 31, 2026 13:13
@JoshuaKGoldberg

Copy link
Copy Markdown
Member Author

Fixes ENG-7200.

@github-actions github-actions Bot locked and limited conversation to collaborators Apr 16, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Scope: Frontend Automatically applied to PRs that change frontend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants