What is the best way to utilize Union Types in v-model within a Vue component's :is directive?

I'm facing a TypeScript error while trying to bind the value of apiRes to v-model. Below is the code snippet where the error occurred. How can I resolve this issue?

Arguments of type { modelValue: Cars | undefined; } cannot be assigned to type NonNullable<(Partial<{}> & Omit<{ readonly modelValue?: Car | undefined; } & VNodeProps & AllowedComponentProps & ComponentCustomProps & Readonly<...> , never> & Record <...>) | (Partial<...> & ... 1 more ... & Record<...>)> & Parameters of Record<...>.
<template>
  <div>
    <component :is="component" v-model="apiRes" />
  </div>
</template>

<script lang="ts" setup>
import test1 from './test1.vue'
import test2 from './test2.vue'
import { computed, ref } from 'vue'

export interface Car {
  age: number
  name: string
}

export interface Car2 {
  door: string
  cvt: string
}

type Cars = Car | Car2

const component = computed(() => {
  const random = Math.random()
  return random > 0.5 ? test1 : test2
})

const apiRes = ref<Cars>()
</script>


//test1
<template>
  <div>{{ props }}</div>
</template>
<script setup lang="ts">
import type { Car } from './test.vue'

const props = defineModel<Car>()
</script>


//test2
<template>
  <div>{{ props }}</div>
</template>
<script setup lang="ts">
import type { Car2 } from './test.vue'

const props = defineModel<Car2>()
</script>

The error vanishes if I change the following line of code, but it might not be the ideal solution:

const apiRes = ref({} as Car)

Answer №1

Agreeing with Tobias on the reason behind the issue (test1 and test2 not accepting Cars, only either Car or Car2), however, I suggest considering alternate solutions:

  • Standardize your interface for test1/test2 (although this may not align with your preferences)
  • If you use v-if/v-else on your components in the template instead of creating a computed property (e.g. by checking for the existence of certain properties), TypeScript will accurately narrow down the type modeled by v-mode

Answer №2

It's important to note that you cannot use Cars in your v-model for test1, which specifically accepts objects of type Car. This is because Cars could refer to Car2, and Car2 does not match the structure of Car. The same applies to test2.

Simply using a union type will not resolve this issue.

In order to suggest an alternative approach for typing apiRes, it would be helpful to understand the purpose of these two components and where apiRes is sourced from. However, the following code snippet should help rectify the error:

const useTest1 = computed(() => Math.random() > 0.5)
const modelCar1 = ref({} as Car)
const modelCar2 = ref({} as Car2)
const component = computed(() => useTest1.value ? test1 : test2)
// then adjust the model based on the component being used

Additionally, ensure that your type definitions are stored in a separate file.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What action is triggered on an Apple iPhone when a notification is tapped?

Currently, I am working on a React application and testing it on an Apple mobile phone. One issue I encountered is that when I receive an SMS, the number appears as a suggestion above the keyboard. I want to be able to tap on this number and have it automa ...

Newest preact and typescript packages causing issues with type validation

Despite my efforts to integrate preact with TypeScript, I have encountered a problem where incorrect types can be passed without any error being raised. I am in the process of transitioning our codebase from plain JavaScript to preact with type scripting. ...

Changing the color of an Angular <div> element with scripting

I am currently working on an Angular 6 project and I need to change the colors of a div tag from a script after a click function. However, I also need to change it back to transparent. When I click on the "Inheritance" option, the background color of the ...

Effective management and structuring of ExpressJS routes

I recently made the switch from PHP to NodeJS and Express, and I must say, it has been quite a learning experience. Following online tutorials to build web apps with Express has been eye-opening. I decided to tackle a project using just JavaScript, but I ...

Data binding in Vue does not function properly within functional components

Clicking the button will cause the number n to increase, but the UI will display it as constant 1. <script> let n = 1 function add() { console.log(n) return ++n } export default { functional: true, render(h, ctx) { return (<div> ...

Example of TypeScript Ambient Namespace Usage

The Namespaces chapter provides an example involving D3.d.ts that I find puzzling. Here is the complete example: declare namespace D3 { export interface Selectors { select: { (selector: string): Selection; (element: ...

Leveraging Vuex in conjunction with dynamically generated components

I am exploring the idea of using Vuex to efficiently manage dynamically generated components in my application. Each page in the app consists of "field" components, with the ability for users to add multiple field components to each page. These field compo ...

Adjusting the position of a stationary element when the page is unresponsive and scrolling

Managing a large web page with extensive JavaScript functionality can be challenging, especially when dealing with fixed position elements that update based on user scroll behavior. A common issue that arises is the noticeable jumping of these elements whe ...

Querying Denormalized Data in AngularFire 0.82: Best Practices and Strategies

I have a question that is related to querying denormalized data with AngularFire. I am looking for a solution specifically using AngularFire (current version 0.82). Here is an example of the data structure I am working with: { "users": { "user1": { ...

Stop the instantiation of type alias

Is there a way to restrict the creation of an instance of a type alias, such as ValidatedEmail? type ValidatedEmail = { address: string; validatedOn: Date } Let's say we have functions validateEmail and sendEmail. const validateEmail = (email): Valid ...

When using setTimeout in NodeJS/Express, a TypeError is thrown stating that it cannot read the property 'client' as it is undefined

My nodejs express route is basic: app.get('/timeout', function (req, res) { setTimeout(() => { console.log('timeout'); }, 2000); res.send({ hello: "world" }); }); However, it's not functioning cor ...

Inspect/Adjust button status upon page initiation

In the realm of my custom MVC framework, a favourite button has been introduced. When this button is pressed, it triggers the appearance of a `successfully added to favourites` div. If clicked again, a `successfully removed from favourites` div appears. T ...

Showing a variety of pictures within a specified time frame

In my CSS, I have defined classes that allow me to display different background images on a page at set intervals: .image-fader { width: 300px; height: 300px; } .image-fader img { position: absolute; top: 0px; left: 0px; animation-name: imagefade; ...

The SQL database is storing data with a timestamp of January 1st, 0001 at 12:00:00 AM

Working with date/time in ASP.NET Core can be challenging, especially for new users. I have an HTML form with fields that initially appear like this: https://i.sstatic.net/eTAdQ.png The code for the Date Joined and Last Changed fields is as follows: < ...

Deactivate the button when the length is less than x

Hey there! I'm new to JavaScript and I'm working on replicating a specific webpage. On this page, there's a button that should be disabled if the login form doesn't have at least 11 characters for the user input and 8 characters for the ...

Implement jquery styling to ajax response

Incorporating a jquery carousel to showcase images within a dynamically updated list has proven fruitful initially. However, once the content within the carousel container is replaced via ajax, all formatting seems to vanish. The root cause of this issue ...

Navigating different domains in ExpressJS - Handling CORS

Currently, I am facing a challenge in setting the domain for a cookie that I am sending along with the response from my ExpressJS implementation. Unfortunately, at the moment, it is only being set to the IP address of where my ExpressJS server is located. ...

AJAX requests sent from different origins to AWS S3 may encounter CORS errors on occasion

My current objective is to access publicly available files stored in S3. The CORS configuration for my S3 setup is as follows: <?xml version="1.0" encoding="UTF-8"?> <CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> < ...

The postman does not retain any data

I am currently facing an issue where I am using Postman to enter a post into a MongoDB server, but the post returns empty. Even after checking my server, nothing has been entered and there are no errors displayed. Here is the route file: router.post(&apos ...

Unable to load Angular 2 Tour of Heroes application due to Typescript issue

My Angular 2 Tour of Heroes app seems to be stuck on the "Loading..." screen and I can't seem to figure out why. The angular-cli isn't showing any errors either. I'm currently at part five of the tutorial and it's becoming quite frustra ...