Reputation: 2053
I'm trying to use the Vue 3.2 <script setup>
tag with TypeScript.
I have a simple use case where I want to display a user ID in the template.
My code is technically working. It displays the user ID just fine.
But there are two weird things...
I have defined a user
prop with a type of User
that I imported from the Firebase SDK. This works, but I get an error on the User
type that says: 'User' only refers to a type, but is being used as a value here. ts(2693)
. Why am I getting this error and how to fix it?
The help docs say I do not need to import { defineProps } from "vue";
. But if I don't do the import I get a 'defineProps' is not defined
error. This is confusing. Why am I forced to import it when the docs say otherwise?
Here is my full code:
<template>
<div>Logged in as {{ user.uid }}</div>
</template>
<script setup lang="ts">
import { defineProps } from "vue"; //Docs say this is not needed, but it throws an error without it
import { User } from "firebase/auth";
defineProps({
user: {
type: User, //ERROR: 'User' only refers to a type, but is being used as a value here. ts(2693)
required: true,
},
});
</script>
Upvotes: 11
Views: 16130
Reputation: 1193
I don't recommend setting up global read only variables in the .eslintrc
, that is not correct and only hides a portion of the configuration issue you may be seeing.
So to begin with, you'll want Volar installed in VSCode and uninstall vetur, and you'll need to add the vue eslint parser to your project with the following command:
npm install --save-dev eslint vue-eslint-parser
and in your .eslintrc.js
file which should be in the root of your project (vue-project/.eslintrc
) you'll want to set your parser to vue-eslint-parser
. a simple .eslintrc
file for a vue ^3.2.6 project can look like this:
module.exports = {
root: true,
env: {
node: true,
'vue/setup-compiler-macros': true,
},
extends: [
'plugin:vue/vue3-essential',
'plugin:vue/vue3-recommended',
],
parser: "vue-eslint-parser",
}
this isn't a minimum example or even complete for vue but a decent start to fixing this specific option and getting linting in your project. note that adding more to the extends array may alter the linting and break this again, namely 'eslint:recommended'
. And for what its worth, I'm not so sure Vue's out-of-the-box linting situation they provide is actually perfect and it still needs some work.
I'd recommend some additional reading at the following links:
https://vuejs.org/guide/scaling-up/tooling.html#linting
https://github.com/vuejs/vue-eslint-parser
https://github.com/vuejs/core/issues/4994#issuecomment-1125677494
Upvotes: 1
Reputation: 1033
in script setup
you can define props like this instead:
<template>
<div>Logged in as {{ user.uid }}</div>
</template>
<script setup lang="ts">
import { defineProps } from "vue"; //Docs say this is not needed, but it throws an error without it
import { User } from "firebase/auth";
defineProps<{ user: User }>();
</script>
another solution is as @bassxzero suggested, you can use
defineProps<{ user: { type: Object as PropType<User>; required: true } }>()
without using withDefaults
it will be automaticly required
EDIT: The answer below this line is outdated, it was based on this old docs. you should check the newer docs here.
also, about:
import { defineProps } from "vue"; //Docs say this is not needed, but it throws an error without it
you actually don't need to import it, but you need to define it inside .eslitrc.js
globals: {
defineProps: 'readonly',
defineEmits: 'readonly',
defineExpose: 'readonly',
withDefaults: 'readonly'
}
Upvotes: 20
Reputation: 841
This solved the problem for me
.eslintrc.cjs
extends: [...],
env: {
"vue/setup-compiler-macros": true,
},
rules: {...}
Upvotes: 3