VueJS 3 Composition API and TypeScript type issue when passing props into setup: Property 'user' does not exist on type
For validator
and default
in the prop
declarations, the Vue docs prescribe either (1) using an arrow function, or (2) provide an explicit this
parameter:
WARNING
Because of a design limitation in TypeScript when it comes to type inference of function expressions, you have to be careful with
validator
anddefault
values for objects and arrays:import { defineComponent, PropType } from 'vue'interface Book { title: string year?: number}const Component = defineComponent({ props: { bookA: { type: Object as PropType<Book>, // Make sure to use arrow functions default: () => ({ title: 'Arrow Function Expression' }), validator: (book: Book) => !!book.title }, bookB: { type: Object as PropType<Book>, // Or provide an explicit this parameter default(this: void) { return { title: 'Function Expression' } }, validator(this: void, book: Book) { return !!book.title } } }})
Anders Hejlsberg, lead architect of TypeScript, explains the issue in a GitHub comment:
This is a design limitation. Similar to #38872. A[n] arrow function with no parameters is not context sensitive, but a function expression with no parameters is context sensitive because of the implicit
this
parameter. Anything that is context sensitive is excluded from the first phase of type inference, which is the phase that determines the types we'll use for contextually typed parameters. So, in the original example, when the value for thea
property is an arrow function, we succeed in making an inference forA
before we assign a contextual type to the a parameter ofb
. But when the value is a function expression, we make no inferences and thea
parameter is given typeunknown
.
Original answer:
One of your props doesn't match the expected signature of PropOptions
, which apparently breaks the type inference for the props
argument in setup()
. Specifically, TypeScript doesn't see that the signature of size.validator
matches up with the type of PropOptions.validator
for some reason.
Interestingly, if you change validator
to an arrow function, the type inference for props
succeeds:
export default defineComponent({ props: { size: { type: String, required: false, default: 'lg', //validator: function (value: string) { /*...*/ }, validator: (value: string) => { /*...*/ }, }, }})