Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

defineModel has wrong type when used with @update:model-value event #12817

Closed
thomasaull opened this issue Feb 6, 2025 · 8 comments · Fixed by vuejs/language-tools#5171
Closed
Labels
language-tools related to vue language-tools scope: types

Comments

@thomasaull
Copy link

Vue version

3.5.13

Link to minimal reproduction

https://play.vuejs.org/#eNqVUslu20AM/RViLpYBQ3I3FHBlo1sOLdAFbXobIFYlSlE6mlFncRy4+veSo1o1iiZBLgKHfKQeH99BvOr7dBdQrETuStv2Hhz60IMqdLOWwjspNlK3XW+shwNYrGGA2poOZtQ2m0pvTNf/yacZP3gqlaXOMthWhccttA6K0odCqRvYvqUU/IKgK6xbjdUWvgcP/hItMlAb8Dc9AlprrNR10KVvjQajv/U8jdsTDlbA4RwOUgOURjujMFWmSWan0NkCOJwzoUHqPBuXpdXo4bHrFVXpBZDHTV6G2LriD8lwOkoKyAiZZ1ObWJBO9Ou6bdIrZzSJGdlIUdKsVqH91DN50nI18uQayWCu38ectwEXx3x5ieWP/+Sv3J5zUny26NDuiMhU84Vt0I/ls68fcU/xVOxMFRSh7yh+QZItMMcR9prOQrRPcJHtu3jrVjfn7mzvUbvjUkyUkUPES0G3ZxlvW/0v3Sfp09hHVyEVj765x418ZQ/EHFV00RpGD33gTM6pTTLjc9HV4z8t/gytxWoFdaEcMR2iEWj2eduhCT5J5rDejOBpbrorVODpGq+jyRLqGhbwbLmcv3hI/+Tx2P7oYjkOuMOE/9rrYoeWxSZhSLH08XMx/AaVXUHO

Steps to reproduce

  • Run the playground
  • Check the console
  • The onUpdateDate method is called twice, the first time with a Date the second time with undefined. The typescript types don’t reflect this behaviour

What is expected?

The types should indicate that the event payload can be Date | undefined

What is actually happening?

The event payload is typed as Date

System Info

Any additional comments?

Types as they show up in my IDE (VS Code):

  • const modelDate: ModelRef<Date | undefined, string, Date | undefined, Date | undefined>
  • (property) "onUpdate:date"?: ((date: Date) => any) | undefined

Please note that the SFC Playground (at least for me) doese not show the types correctly for some reason

@jh-leong jh-leong added scope: types language-tools related to vue language-tools labels Feb 7, 2025
@jh-leong
Copy link
Member

jh-leong commented Feb 7, 2025

As a workaround:

- const modelDate = defineModel<Date>('date', {
+ const modelDate = defineModel<Date | undefined>('date', {
    required: false
  })

@RylanBueckert-Broadsign

The @update:model-value event should only be able to be undefined if it is not required and there is not a default. The fix made to vue-tsc v2.2.2 does not check if a default value was given.

@KazariEX
Copy link
Member

It has been fixed by vuejs/language-tools@1e84c6a.

@RylanBueckert-Broadsign

It has been fixed by vuejs/language-tools@1e84c6a.

@KazariEX Looking at the change, I am not sure it will always work. What if the default value is a falsy value like 0 or an empty string? Shouldn't the check be more like:
if (!defineModel.required && !('defaultValue' in defineModel)) {
or
if (!defineModel.required && defineModel.defaultValue !== undefined) {

@KazariEX
Copy link
Member

My mistake. Could you please open a PR for it?

@thomasaull
Copy link
Author

The @update:model-value event should only be able to be undefined if it is not required and there is not a default. The fix made to vue-tsc v2.2.2 does not check if a default value was given.

@RylanBueckert-Broadsign I think this is not correct for non-required models with a default value, since nothing is stopping you from doing myModel.value = undefined at a later stage, right?

@RylanBueckert-Broadsign
Copy link

RylanBueckert-Broadsign commented Feb 19, 2025

The @update:model-value event should only be able to be undefined if it is not required and there is not a default. The fix made to vue-tsc v2.2.2 does not check if a default value was given.

@RylanBueckert-Broadsign I think this is not correct for non-required models with a default value, since nothing is stopping you from doing myModel.value = undefined at a later stage, right?

@thomasaull vue-tsc does show me an error if I try to set a model with a default value to undefined (both in my IDE and if I build).

const model = defineModel<number | null>({ default: null });

model.value = undefined; // Error here: Type 'undefined' is not assignable to type 'number | null'

@thomasaull
Copy link
Author

@RylanBueckert-Broadsign Yes you’re right, the type changes from string | undefined to string when a default value is set:

const model = defineModel<string>() // ModelRef<string | undefined, string>
const model = defineModel<string>({ default: 'test' }) // ModelRef<string, string>

@github-actions github-actions bot locked and limited conversation to collaborators Mar 6, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
language-tools related to vue language-tools scope: types
Projects
None yet
5 participants