Using Partial<Type> on a Vue3 reactive() object is acting strangely

jmpp

I'm facing a weird behavior when using a TypeScript Partial type with a Vue3 reactive object.

I have a simple type representing a User, and need to create a user that may not have some properties at first, so I used a Partial utility type :

type User = {
  id: number
  name: string
}

const user_1: Partial<User> = {
  name: 'John'
}

// ✅ Everything's fine here

Obviously when I try to put something else in that user, it throws an error :

const user_1: Partial<User> = {
  name: 'John',
  alive: true
  // ❌ Type '{ … }' is not assignable to type 'Partial<User>' […] 'alive' does not exist in type 'Partial<User>'
}

This is what I expect from plain TypeScript so no problem here.

But the strange behavior occurs when I try to declare a Vue3 reactive object with that partial :

import { reactive } from 'vue'

const user_2: Partial<User> = reactive({
  id: 42,
  name: 'Gerald',
  alive: true
})

Here everything seems to be clear for TypeScript which doesn't yield anything.

What's strange is when I use that user_2.alive in the template, the error shows up as expected :

<template>
  <h1>{{ user_2.alive }}</h1>
  <!-- ❌ Property 'alive' does not exist on type 'Partial<User>' -->
</template>

So, why can't I see the error at the declaration of the reactive object ? Did I omit something important or could that be a bug in the implementation of TS with reactive()?

Note: I also tried using the default setup() declaration, in cas of it would be a bug with the annotation, but the problem still remains

I could also reproduce the bug on the Vue3 Playground interface here : https://play.vuejs.org/#eNp9UstOwzAQ/JWVLwUJpeJxCqESIIToASoeN19Muk1dHNuynVIU5d9ZO7QEqfTm3RnPzj5adm1ttm6Q5azwpZM2gBK6uuIseM7AY2jshGtZW+MCtOBQlEGuETpYOFPDiP6OLrnmOnxZhDePDq6g5RpAznPQTf2O7iSGWtSYgw9O6iolREVxT+C6ixKl0T6ANq4WKirlMBMuSKGKGE2GwhdnA9HR1Cz1qBdVZC6HhVAeSTU562W3zvcLb9GjfyrcoxNq/qdGcE0scUw1inE/O5oUBQFrq0RAigCK5emkbQdNZVERug6KMUEDytBglmoQ64dUjHei7IRWQy0tZJWtvNG0ueSZs9LUVip0TzZIapmzvJ9XxIRS5nOactF36iP9WWL5sSe/8puY42zmkPyskbMdFoSrMPTw3csjbui9A2szbxSxD4DP6I1qoseedtPoOdke8JLbh3RzdC2v/m4TUPttU/3gAbrE54xO8PZA6792z7Pz9I+2xrpvqPX/OQ==

kelsny

You can pass a type parameter to reactive to say that the argument it takes must be of that type:

const user_2 = reactive<Partial<User>>({
  id: 42,
  name: 'Gerald',
  alive: true, // ERROR
});

Otherwise, it will be inferred automatically. Since excess properties are allowed in assignment (here, assigning returned value from function call to user_2), the assignment is allowed.

Playground

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related