eslint-plugin-vue icon indicating copy to clipboard operation
eslint-plugin-vue copied to clipboard

vue/require-valid-default-prop not always detecting interface in seperate .ts file

Open Nicolas-Yazzoom opened this issue 3 years ago • 7 comments

Checklist

  • [x] I have tried restarting my IDE and the issue persists.
  • [x] I have read the FAQ and my problem is not listed.

Tell us about your environment

  • ESLint version: v8.22.0
  • eslint-plugin-vue version: 9.4.0
  • Node version: v16.15.1
  • Operating System: Windows 10 (64 bit) + WSL Ubuntu 18.04.2 LTS

Please show your full configuration:

{
  "env": {
    "browser": true,
    "node": true
  },
  "extends": [
    "eslint:recommended",
    "plugin:vue/vue3-recommended",
    "plugin:@typescript-eslint/recommended",
    "prettier"
  ],
  "parser": "vue-eslint-parser",
  "parserOptions": {
    "ecmaVersion": "latest",
    "parser": "@typescript-eslint/parser", 
    "sourceType": "module"
  },
  "plugins": [
    "vue",
    "@typescript-eslint"
  ],
  "rules": {
    "vue/multi-word-component-names": "off",
    "vue/no-reserved-component-names": "off",
    "no-console": "off",
    "no-debugger": "off"
  }
}

What did you do?

// types/file.ts
interface Label {
  label: string
  plural: boolean
}

export { Label }

<script setup lang="ts">
import { Label } from '@/types/file.ts'

withDefaults(
  defineProps<{
    label?: string | Label
  }>(),
  {
    // This appears to be incorrect but should be accepted
    label: () => ({ label: 'label', plural: true }),
    // This is correct
    label: () => {
      return { label: 'label', plural: true }
    }

  }
)

</script>

What did you expect to happen? Both ways of setting the default should be accepted.

What actually happened?

  114:19  error  Type of the default value for 'label' prop must be a string  vue/require-valid-default-prop

When Label is in a different .ts file linting fails with the above error. When moving the definition of Label into the Vue file linting issue is solved. There appears to be a difference in behaviour depending on how you specify the function which is also not expected.

Repository to reproduce this issue

https://github.com/Nicolas-Yazzoom/eslint-plugin-vue-bug

Nicolas-Yazzoom avatar Sep 05 '22 11:09 Nicolas-Yazzoom

Added repro

Nicolas-Yazzoom avatar Sep 05 '22 12:09 Nicolas-Yazzoom

I think you need to define the type definition inside vue. https://vuejs.org/guide/typescript/composition-api.html#syntax-limitations

The following demo prints a warning to the console. https://sfc.vuejs.org/#eNp9UU1rwzAM/SvCl6TQJveQdgx23GE/wBe3VVqXxDay0g4y//cpX9BtsJOtJ+mh996gXkMo7j2qStXxRDYwROQ+QGvcZa8VR60O2tkueGIY4N0csYUEDfkOsqJsbIsFx0y7h+XrGzambznm2gGcsbEOP8iHWA8jAEIq2y8VRCbrLvA10429dMg32/HzPFlBvoH9AfJhrbPpzbYQ2p6MAEw9QppXk3Yb7bSry1mJ3C0FYxdawyjVMEzrSQbr8glXWzUL3HUmFLfondgxHaKXhrhQradpJX6NtVZX5hCrsozNaTTxFgtPl1J+BfWObYcFxm53JP+ISEKs1XTowlEKeEfaEbozEtJ/nL9G//Au+pNIWSIRCdYxUmNOuMQ2CVicnCMYgdXKo/ctGrFMeLTDz5+Jq/QNdRq/dA==

ota-meshi avatar Sep 05 '22 15:09 ota-meshi

Hello there

From the docs:

"The interface or object literal type can contain references to types imported from other files, however, the generic argument itself passed to defineProps cannot be an imported type."

In this case the literal contains a reference to the Label interface imported from file.ts so I believe it should be allowed, no? Also, thank you for the simplified repro! :)

Nicolas-Yazzoom avatar Sep 05 '22 15:09 Nicolas-Yazzoom

I'm not familiar with English, so I may have misunderstood the documentation, but it's true that vue's runtime is giving warnings. Since the warning is also displayed at runtime, I think we can judge that the rule is working correctly.

ota-meshi avatar Sep 05 '22 15:09 ota-meshi

My bad, I misread the error. So this means label: () => ({ label: 'label', plural: true }) and label: () => { return { label: 'label', plural: true }} are not functionally equivalent? I used to do this in Vue 2 all the time without issue. Is there a difference?

Nicolas-Yazzoom avatar Sep 05 '22 15:09 Nicolas-Yazzoom

I didn't realize it. I think it's a false negative in the rule that the label: () => { return { label: 'label', plural: true }} is not warned.

ota-meshi avatar Sep 05 '22 15:09 ota-meshi

@Nicolas-Yazzoom Yes, they are functionally equivalent.

FloEdelmann avatar Sep 05 '22 16:09 FloEdelmann

This was probably fixed in v9.13.0. I'll close this issue for now, feel free to comment or open a new issue if it is not fixed.

FloEdelmann avatar Jun 22 '23 11:06 FloEdelmann