Variable type linked to interface content type

Is it possible to link two fields of an interface together? I have the following interface:

export interface IContractKpi {
  type: 'shipmentVolumes' | 'transitTime' | 'invoices';
  visible: boolean;
  content: IKpiContent;
}

export type IKpiContent =
  | IKpiShipmentVolumeContent[]
  | IKpiTransitTimeContent[]
  | IKpiInvoicesContent;

My goal is for TypeScript to understand that:

When type is 'shipmentVolumes', content should be IKpiShipmentVolumeContent[].

When type is 'transitTime', content should be IKpiTransitTimeContent[].

When type is 'invoices', content should be IKpiInvoicesContent.

The situation I am dealing with involves getting a response from the backend:

kpis: IContractKpi[]

I have a component that takes in kpi: IContractKpi as props. This component dynamically renders different components based on the type using a lookup table:

const lookup: Record<'shipmentVolumes' | 'transitTime' | 'invoices', VueComponent> = {
 shipmentVolumes: KpiShipmentVolumes,
 transitTime: KpiTransitTime,
 invoices: KpiInvoices,
}


const kpiComponent = computed(() => lookup[kpi.type])

<template>
 <component :is="kpiComponent" :content="kpi.content" /> <--- I hope TypeScript isn't angry with me here :D
</template>

I can make the code simpler, but that is not the ideal solution.

<template>
 <KpiShipmentVolumes v-if="kpi.type === 'shipmentVolumes'" :content="kpi.content" /> <--- this approach still causes issues
 <KpiTransitTime v-if="kpi.type === 'transitTime'" :content="kpi.content" />
 <KpiInvoices v-if="kpi.type === 'invoices'" :content="kpi.content" />
</template>

Answer №1

When dealing with different states, it is common practice to use a union.

export type IContractKpi = ({
  type: 'shipmentVolumes'
  content: IKpiShipmentVolumeContent[];
} | {
  type: 'transitTime' 
  content: IKpiTransitTimeContent[];
} | { 
  type:  'invoices' 
  content: IKpiInvoicesContent[];
}) & {
  visible: boolean;
}

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

Invalid Type Property - Request and Response Express Types

When I try to utilize the Request or Response types in this manner: app.use('*', (req: Request, res: Response, next: NextFunction) => { res.set('Cache-Control', 'no-store'); const requestId: string = req.headers[&a ...

Looking to incorporate an additional column 'LastName' that can be used for filtering in the Angular data table code. This column will be included if it is present in the data

function applyFilter(filterValue: string) { filterValue = filterValue.toLowerCase(); --- return filtered result return this.dataSet.filter( (item: any) => item.name ? item.name.toLowerCase(). ...

Why isn't the parent (click) event triggered by the child element in Angular 4?

One of my challenges involves implementing a dropdown function that should be activated with a click on this specific div <div (click)="toggleDropdown($event)" data-id="userDropdown"> Username <i class="mdi mdi-chevron-down"></i> </d ...

Tips for Setting up SQLite Database Connection in VueNative App

Struggling to establish a connection to SQLite database in vueNative. Unsure of the steps to take. Could someone lend a hand? Seeking guidance on how to connect to SQLite db within a vueNative app. ...

FullCalendar and VUE Integration: In need of FullCalendar view plugins

FullCalendar Troubleshooting Greetings! I've been encountering some issues while trying to run the FullCalendar plugin in my project. Strangely, it worked perfectly fine on a different server before. Here's the code snippet I'm using. I am ...

Leveraging Global Variables and Functions with Webpack and TypeScript

I have been utilizing Webpack in conjunction with TypeScript, HTML, and SCSS to develop a project. My goal is to create a single page application that incorporates a router located within the root folder of the project /framework/, with all my source code ...

Error loading resource in Vue npm run serve: net::ERR_CONTENT_LENGTH_MISMATCH

I am encountering the following error message in Google Chrome console: Failed to load resource: net::ERR_CONTENT_LENGTH_MISMATCH chunk-vendors.js:1 This results in a blank page when attempting to load a Vue development page initiated with: user@ubuntu:~# ...

Display a loader in Vue JS at the start and then remove it once the response is received

To achieve the functionality of showing a loader initially and hiding it after receiving a response, you can use the following code: <template> <div id="app"> <Document :loading="loading"> </div> </tem ...

No data is generated when choosing from the dropdown menu in mat-select

I have a select function where all options are selected, but the selected sections are not shown. When I remove the all select function, everything works fine. Can you help me find the error? Check out my work on Stackblitz Here is my code: Select <m ...

The Observable pipeline is typically void until it undergoes a series of refreshing actions

The issue with the observable$ | async; else loading; let x condition usually leads to staying in the loading state, and it requires multiple refreshes in the browser for the data to become visible. Below is the code snippet that I utilized: // TypeScript ...

The dropdown cannot be disabled because it is being passed as an input parameter

We are currently utilizing PrimeNG along with Angular 15. Scenarios: According to the requirements, we need the ability to disable the PrimeNG dropdown control based on a selection. Problem: The disabled property of <p.dropdown> is not functioning ...

Error encountered in production mode - TypeError: o is not a function in Vue/webpack/Laravel Mix

Good day. I am utilizing Vue 2 alongside Laravel Mix/Webpack and Node version 14.18.1. Running 'npm run dev' works perfectly fine for me. However, when I execute 'npm run production', I encounter an error saying: TypeError: o is not a ...

Guide on showing a component exclusively for iPads with React and TypeScript

I need help displaying an icon only in the component for iPad devices, and not on other devices. As a beginner in coding for iPads and mobile devices, I am unsure how to achieve this specific requirement for the iPad device. Below is the code snippet tha ...

When compiling, VUE fails to load page content

I am facing an issue with my VUE program that works perfectly locally but fails to work after compiling. The main concept is to load content from other files within the initial VUE App.vue file, specifically the Home.vue file App.vue <template> & ...

Unable to alter Mui input label color upon focus using theme.ts

In my next.js app, I'm facing an issue with changing the color of the label in a Material UI input field using Mui. Despite updating the theme.ts file to change the border bottom color and label color, only the border bottom color is being applied. T ...

Can you explain how I can showcase JSON object values within an Angular framework?

After fetching data through a REST API in Angular, I need to display only the "classLevelPermissions" in table format as shown in the .html file. .ts - async getclp(className: string) { debugger; this.clplist = []; this.className = className ...

Enable a VueJS directive on-the-fly from a separate directive

My goal is to simplify the process of binding a form control to vuejs by creating a directive that handles all necessary events for tracking changes in a form field. Rather than manually adding multiple event listeners like this: <input type="text" na ...

Vue 3 has officially deprecated the use of ::v-deep as a combinator. Going forward, please utilize ::v-deep(<inner-selector>) instead

Recently, an error message has been popping up in Vue 3 regarding the use of ::v-deep. The warning states that using ::v-deep as a combinator is deprecated. Instead, it recommends using ::v-deep(<inner-selector>) Here is an example of the CSS ...

Vue: Exploring the Restriction of Using refs in Component Templates

I can't seem to figure out Vue refs. Whenever I define them in my main Vue instance's template, they work perfectly fine. However, when I define them within a component template, they don't seem to work at all. What could be causing this iss ...

Advantages of incorporating lazy loading in a Vue Single Page Application:

What level of realistic benefit can be expected from lazy loading in a Vue application using Vue-router, Vuex, and many components to improve initial load times in an SPA? In comparison to minifying and bundling code (in this case, with gulp), do the perf ...