Skip to content

useVueValidDefineProps (JavaScript)

Language JavaScript (and super languages)
biome.json
{
"linter": {
"rules": {
"nursery": {
"useVueValidDefineProps": "error"
}
}
}
}

Enforce valid defineProps() calls in Vue components.

In <script setup>, a component declares its props with defineProps(). Vue reads this call when it compiles the component, so the call has to follow some rules. This rule reports a defineProps() call when:

  • its argument uses a variable declared in <script setup>. Vue moves the argument out of the setup code, where these variables don’t exist;
  • it declares the props both with a type, as in defineProps<{ msg: string }>(), and with an argument, as in defineProps({ msg: String });
  • the component calls it more than once;
  • the default export of the plain <script> block also declares props with the props option;
  • it declares no props, and the plain <script> block doesn’t declare any either.

The rule checks the defineProps() calls at the top level of <script setup>: a call written as a statement of its own or as the value of a variable, also when it’s wrapped in withDefaults().

<script setup>
const definition = { msg: String };
defineProps(definition);
</script>
code-block.vue:3:13 lint/nursery/useVueValidDefineProps ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

✖ defineProps() uses definition, which is declared in <script setup>.

1 │ <script setup>
2 │ const definition = { msg: String };
> 3 │ defineProps(definition);
│ ^^^^^^^^^^
4 │ </script>
5 │

ℹ Vue moves the argument of defineProps() out of the setup code when it compiles the component, so the argument can't use variables declared in <script setup>.

ℹ Import the value from another file, or declare it in a plain <script> block.

ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.

<script setup lang="ts">
defineProps<{ msg?: string }>({ msg: String });
</script>
code-block.vue:2:1 lint/nursery/useVueValidDefineProps ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

✖ defineProps() declares the props both with a type and with an argument.

1 │ <script setup lang="ts">
> 2 │ defineProps<{ msg?: string }>({ msg: String });
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3 │ </script>
4 │

ℹ Vue can't use both at the same time, and fails to compile the component.

ℹ Declare the props either with a type between <> or with an argument between ().

ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.

<script setup>
defineProps({ msg: String });
defineProps({ count: Number });
</script>
code-block.vue:3:1 lint/nursery/useVueValidDefineProps ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

✖ defineProps() is called more than once.

1 │ <script setup>
2 │ defineProps({ msg: String });
> 3 │ defineProps({ count: Number });
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4 │ </script>
5 │

ℹ It's first called here.

1 │ <script setup>
> 2 │ defineProps({ msg: String });
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3 │ defineProps({ count: Number });
4 │ </script>

ℹ A component declares its props once, and Vue fails to compile a component that calls defineProps() several times.

ℹ Declare all the props in a single defineProps() call.

ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.

<script>
export default {
props: { msg: String },
};
</script>
<script setup>
defineProps({ count: Number });
</script>
<script setup>
defineProps();
</script>
<script setup>
import { definition } from "./definition";
defineProps(definition);
</script>
<script setup lang="ts">
defineProps<{ msg?: string }>();
</script>
<script>
const definition = { msg: String };
</script>
<script setup>
defineProps(definition);
</script>