Vue version
3.5.27
Link to minimal reproduction
https://github.com/DerZade/vue-tsc-exact-optional-prop-types-error
Steps to reproduce
- Create a project with
npm create vue@latest
- Turn on
exactOptionalPropertyTypes in your tsconfig.app.json
- Create a component with a separate type of
defineProps:
<template><!-- irrelevant --></template>
<script lang="ts" setup>
export type CompProps = {
somethingOptional?: string; // the optional (?) is important
};
const props = defineProps<CompProps>();
</script>
- Create wrapper component for first component and re-use the props type in its
defineProps:
<template>
<Comp v-bind="props" /> <!-- This v-bind will error -->
</template>
<script setup lang="ts">
import Comp from './Comp.vue';
import type { CompProps } from './Comp.vue';
const props = defineProps<CompProps>();
</script>
What is expected?
vue-tsc not to error :D
What is actually happening?
$ npm run type-check
> vue-tsc-exact-optional-prop-types@0.0.0 type-check
> vue-tsc --build
src/App.vue:3:6 - error TS2379: Argument of type '{ somethingOptional: string; }' is not assignable to parameter of type '{ readonly somethingOptional?: string; } & VNodeProps & AllowedComponentProps & ComponentCustomProps & Record<string, unknown>' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties.
Type '{ somethingOptional: string; }' is not assignable to type '{ readonly somethingOptional?: string; }' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties.
Types of property 'somethingOptional' are incompatible.
Type 'string | undefined' is not assignable to type 'string'.
Type 'undefined' is not assignable to type 'string'.
3 <Comp v-bind="props" />
~~~~
Found 1 error.
System Info
System:
OS: Linux 6.18 Fedora Linux 42 (Workstation Edition)
CPU: (16) x64 AMD Ryzen 7 7840U w/ Radeon 780M Graphics
Memory: 44.07 GB / 60.62 GB
Container: Yes
Shell: 5.2.37 - /bin/bash
Binaries:
Node: 22.19.0 - /home/jonas/.nvm/versions/node/v22.19.0/bin/node
Yarn: 1.22.22 - /usr/local/sbin/yarn
npm: 11.7.0 - /home/jonas/.nvm/versions/node/v22.19.0/bin/npm
pnpm: 10.12.1 - /home/jonas/.local/share/pnpm/pnpm
bun: 1.1.42 - /home/jonas/.bun/bin/bun
Deno: 2.5.4 - /home/jonas/.deno/bin/deno
Browsers:
Chrome: 144.0.7559.59
Firefox: 147.0
Firefox Developer Edition: 147.0
Any additional comments?
This might be a duplicate of #6532 and I reported this issue initially as vuejs/language-tools#5947
Looks like the defineProps<T> returns the optional properties of T with | undefined instead of keeping it actually optional with the ?. So { foo?: string } becomes { foo: string | undefined }, which will make it incompatible if exactOptionalPropertyTypes is enabled, therefore it is not accepted in the v-bind.
Vue version
3.5.27
Link to minimal reproduction
https://github.com/DerZade/vue-tsc-exact-optional-prop-types-error
Steps to reproduce
npm create vue@latestexactOptionalPropertyTypesin yourtsconfig.app.jsondefineProps:defineProps:What is expected?
vue-tscnot to error :DWhat is actually happening?
System Info
System: OS: Linux 6.18 Fedora Linux 42 (Workstation Edition) CPU: (16) x64 AMD Ryzen 7 7840U w/ Radeon 780M Graphics Memory: 44.07 GB / 60.62 GB Container: Yes Shell: 5.2.37 - /bin/bash Binaries: Node: 22.19.0 - /home/jonas/.nvm/versions/node/v22.19.0/bin/node Yarn: 1.22.22 - /usr/local/sbin/yarn npm: 11.7.0 - /home/jonas/.nvm/versions/node/v22.19.0/bin/npm pnpm: 10.12.1 - /home/jonas/.local/share/pnpm/pnpm bun: 1.1.42 - /home/jonas/.bun/bin/bun Deno: 2.5.4 - /home/jonas/.deno/bin/deno Browsers: Chrome: 144.0.7559.59 Firefox: 147.0 Firefox Developer Edition: 147.0Any additional comments?
This might be a duplicate of #6532 and I reported this issue initially as vuejs/language-tools#5947
Looks like the
defineProps<T>returns the optional properties ofTwith| undefinedinstead of keeping it actually optional with the?. So{ foo?: string }becomes{ foo: string | undefined }, which will make it incompatible ifexactOptionalPropertyTypesis enabled, therefore it is not accepted in thev-bind.