Subscribe on changes!

`defineProps` seems to ignore props marked as optional and requires them anyway when using TypeScript tooling

avatar
Mar 8th 2022

Version

3.2.31

Reproduction link

stackblitz.com

Steps to reproduce

Create a new project using the following command:

$ npm create vite@latest
$ npm install

Use Vue and TypeScript.

Then, create a new component CustomComponent.vue (the name doesn't really matter) with the following content:

<script setup lang="ts">
const $props = defineProps({
  text: {
    type: String,
    required: true,
  },
  optional: {
    type: String,
    required: false,
    default: 'this is not required'
  },
});
</script>

<template>
  {{ $props.text }}
</template>

Now, when importing the component into another component, omitting the non-required prop will cause a type error.

script-setup-code

script-setup-error

Notice that this doesn't happen when using the Options API, only when using script-setup:

<script lang="ts">
import { defineComponent } from 'vue';

export default defineComponent({
  name: 'CustomComponent',
  props: {
    text: {
      type: String,
      required: true,
    },
    optional: {
      type: String,
      required: false,
      default: 'this is not required'
    },
  },
});
</script>

<template>
  {{ text }}
</template>

options-code

What is expected?

The TypeScript tooling should recognize that the optional prop is not required.

What is actually happening?

The TypeScript tooling seems to think that the optional prop is required.


This doesn't seem to be an issue when defining props with the interface syntax:

<script setup lang="ts">
const $props = defineProps<{
  text: string,
  optional?: string,
}>();
</script>

<template>
  {{ $props.text }}
</template>

interface-syntax-code

However, when using the withDefaults compiler macro with the interface syntax, the exposed interface once again seems to ignore some values are marked as optional:

<script setup lang="ts">
const $props = withDefaults(defineProps<{
  text: string,
  optional?: string,
}>(), {
  optional: 'this is optional',
});
</script>

<template>
  {{ $props.text }}
</template>

with-defaults-code

with-defaults-error

I should point out that the compilation process itself works fine. It just seems to be the tooling that's failing randomly.

avatar
Mar 8th 2022

Hm, this seems to be related to the variable name you chose. $props is part of the Vue component API, and it seems it's somehow confusing Volar. Changing it to const props fixed the issues, changing it back made them reappear.

this issue should likely be moved to the Volar repo: https://github.com/johnsoncodehk/volar