vuejs/eslint-plugin-vue

Vue ESLint: false positive of vue/no-async-in-computed-properties due to using zod .catch inside a computed

Closed this issue · 1 comments

Tell us about your environment

  • ESLint version: ^9.33.0
  • eslint-plugin-vue version: ^10.4.0
  • Vue version: ^3.5.18
  • Node version: 22
  • Operating System: Windows

Please show your full configuration:

export default withNuxt(
  storybook.configs['flat/recommended'],
  {
    rules: {
      '@typescript-eslint/no-explicit-any': 'off',
      '@typescript-eslint/ban-ts-comment': 'off',
      'no-irregular-whitespace': 'off',
      'vue/multi-word-component-names': 'off',
      'vue/no-v-html': 'off',
      'vue/script-indent': [
        'error',
        2,
        {
          baseIndent: 1,
        },
      ],
    },
  },
  {
    files: ['**/*.vue'],
    rules: {
      '@stylistic/indent': 'off',
    },
  },
)

What did you do?

  const router = useRouter()

  const filter = computed(() => z.safeParse(
    z.object({
      'filter[name]': z.catch(
        z.nullish(
          z.string()
            .check(z.minLength(2))
            .check(z.maxLength(20)),
        ),
        '',
      ),
      'filter[city]': (
        z.nullish(z.pipe(
          z.union([
            z.number(),
            z.string(),
          ]),
          z.transform(Number),
        ))
      ),
      'filter[status]': z.nullish(z.enum(['anybody', 'pregnant', 'mother', 'planning'])),
    }),
    router.currentRoute.value.query,
  ))

What did you expect to happen?

No lint error when there are no real Promise/async operations; synchronous Zod chains with .catch should be allowed.

What actually happened?

A Vue component uses a Zod validation chain inside a computed that calls z.catch, which does not initiate any asynchronous operations, but the linter throws: “Unexpected asynchronous action in computed function. (vue/no-async-in-computed-properties)”

This rule currently identifies Promise/async operations based on the names in PROMISE_FUNCTIONS (e.g., catch, then, etc.).

We could add an option to ignore specific name values, such as z. So we can use z.catch() or z.string().catch()