Skip to content

fix: false positive for returns in exhaustive switch#3067

Open
EdRW wants to merge 5 commits intovuejs:masterfrom
EdRW:fix-false-positive-for-exhaustive-switch
Open

fix: false positive for returns in exhaustive switch#3067
EdRW wants to merge 5 commits intovuejs:masterfrom
EdRW:fix-false-positive-for-exhaustive-switch

Conversation

@EdRW
Copy link
Copy Markdown

@EdRW EdRW commented Apr 12, 2026

Description

Currently return-in-computed-property and require-render-return report an error for switch statements without a default case, when the switch is the final statement. For Typescript users the error is shown even when the final statement is a switch statements that exhaustively calls return or throw for every case.

This PR updates executeOnFunctionsWithoutReturn to use typescript-eslint/parser services (when available) to verify exhaustive switch statements.

No behavior changes for Javascript users. Switch statements without default case will still show an error when typing info is not available.

Supported patterns

This implementation borrows much from typescript-eslint's implementation of switch-exhaustiveness-check.ts, and supports:

  • String/number/bigint literal unions
  • Numeric and string enums
  • Boolean (true | false)
  • Nullable types (T | null, T | undefined)
  • Branded/intersection types
  • Discriminated unions (e.g., switch (event.type))
  • Generic components

Most of the lines added in this PR are just test cases to check all of these patterns.

Screenshots

return-in-computed-property

Examples come from #2142

Exhaustive

Screenshot 2026-04-12 at 20 38 57

Non-exhaustive

Screenshot 2026-04-12 at 20 38 49

require-render-return

Examples come from #2100

Exhaustive

Screenshot 2026-04-12 at 21 05 10

Non-exhaustive

Screenshot 2026-04-12 at 21 09 00

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 12, 2026

🦋 Changeset detected

Latest commit: 421d9f2

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
eslint-plugin-vue Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@EdRW EdRW changed the title Fix false positive for exhaustive switch fix: false positive for returns in exhaustive switch Apr 12, 2026
Comment on lines +355 to +369
/**
* @param {Type} type
* @param {typeof import('typescript')} ts
* @returns {boolean}
*/
function isTypeLiteralLike(type, ts) {
return (
(type.flags &
(ts.TypeFlags.Literal |
ts.TypeFlags.Undefined |
ts.TypeFlags.Null |
ts.TypeFlags.UniqueESSymbol)) !==
0
)
}
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Basically copied from switch-exhaustiveness-check.ts#L415

Comment on lines +339 to +353
/**
* @param {Type} type
* @returns {Type[]}
*/
function unionConstituents(type) {
return type.isUnion() ? type.types : [type]
}

/**
* @param {Type} type
* @returns {Type[]}
*/
function intersectionConstituents(type) {
return type.isIntersection() ? type.types : [type]
}
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Inlined TS utility functions from ts-api-utils

Comment on lines +387 to +392
/**
* @param {RuleContext} context
* @param {SwitchStatement} switchNode
* @returns {boolean}
*/
function isExhaustiveSwitch(context, switchNode) {
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

question
Most of the work was done here because it's TS related, but I wasn't sure if this is actually the most appropriate location.
Is there a more suitable place or is it ok keep the exhaustive switch-related logic here?

@EdRW EdRW marked this pull request as ready for review April 12, 2026 14:51
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Since return-in-computed-property and require-render-return share the same logic for exhaustive switch statements, the thorough tests of the full range of supported types probably only need to happen in one place. So they were added here.

Copy link
Copy Markdown
Member

@ota-meshi ota-meshi left a comment

Choose a reason for hiding this comment

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

Thank you for this PR!

}
})
</script>`,
...getTypeScriptFixtureTestOptions()
Copy link
Copy Markdown
Member

@ota-meshi ota-meshi Apr 13, 2026

Choose a reason for hiding this comment

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

(edited)
Could you please add the following test case?

<script setup lang="ts">
import { computed, ref } from 'vue'
const flag = ref<boolean>(true)
const result = computed(() => {
  if (x !== 0) {
    switch (flag.value) {
      case true: return 'yes'
      case false: return 'no'
    }
  } else {
    return 'x === 0'
  }
})
</script>

Is it supported?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Thanks for the review and suggestion.

Is it supported?

Unfortunately, it's not supported yet. I mainly focused on the case where switch is the last statement in the function. In this example, the switch is nested in an if-statement.

Could you please add the following test case?

Sure I can try. It think it'll involve a lot of recursive traversal though😨 . I might also take a look at try/catch as well.

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.

In my opinion, rather than using recursion, it would probably be better to use ESLint's Code Path Analysis to process the relevant switch statements.

https://eslint.org/docs/latest/extend/code-path-analysis

However, you don't need to add support in this PR 😄
I think even just the changes in this PR are a valuable improvement.
Could you please add test cases and leave comments about anything that isn't yet supported?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants