core icon indicating copy to clipboard operation
core copied to clipboard

defineComponent (function syntax): optional props inferred as required

Open zfeher opened this issue 2 months ago • 2 comments

Vue version

3.5.22

Link to minimal reproduction

minimal repro

Steps to reproduce

1, open minimal repo and see the reported error in App.vue at <Comp> usage. It says p1, p2 and p3 required props are missing.

2, open Comp.ts see Comp definition where p1, p2 and p3 are defined as optional props. Hoovering over props in setup func also shows them incorrectly as required.

What is expected?

p1, p2 and p3 props of Comp correctly inferred as optional props like what happens with the similar CompB (options syntax).

What is actually happening?

p1, p2, and p3 props of Comp are inferred incorrectly as required props.

System Info


Any additional comments?

No response

zfeher avatar Oct 05 '25 14:10 zfeher

Image CompB: Image It can be seen that the types of the two are not the same. At this time, TypeScript has inferred it as a required type. TypeScript's function parameter type inference is unidirectional. It cannot "foresee" the type information in the second parameter and apply complex type conversions when parsing the first parameter. Comp: 1.When encountering (props) =>, use the default parameter type inference. 2.Since there is no type information, consider all props as required. 3.By the time the subsequent props options are seen, the previous inference cannot be modified. In CompB: 1.parse the props option. 2.Apply Vue's complex type conversion: ExtractPropTypes + LooseRequired + Readonly. 3.Apply the converted types to the props parameter of the setup function.

xiaocainiao633 avatar Oct 14 '25 13:10 xiaocainiao633

This comes from the official documentation: Image defineComoponent

xiaocainiao633 avatar Oct 14 '25 13:10 xiaocainiao633

for Comp can write like this:

import { type ExtractPublicPropTypes } from "vue";

const props = {
      p1: String,
      p2: { type: Number },
      p3: { type: Boolean, required: false },
      p4: { type: String, required: true },
    },
  }
const Comp = defineComponent<ExtractPublicPropTypes<typeof props>>(
  (props) => {
    return () => h('div', 'Comp');
  },
  {
    name: 'Comp1',
    props
);

but, it's too wordy..... has any roadmap by official ???

8797110103-8955 avatar Dec 17 '25 10:12 8797110103-8955