Home > Net >  Interface content type tied to variable type
Interface content type tied to variable type

Time:10-24

How can I tie two fields of interface together, I have an interface like this:

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

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

What I would like to do is typescript to know that:

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

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

When type is 'invoices', content is IKpiInvoicesContent.

The situation and what I want to achieve is that I get a response from the backend:

kpis: IContractKpi[]

I have a component which accepts kpi: IContractKpi type That component renders different component for each type through a lookupTable:

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" /> <--- here I would like for typescript not be angry with me :D
</template>

I can simplify code but this is not ideal.

<template>
 <KpiShipmentVolumes v-if="kpi.type === 'shipmentVolumes'" :content="kpi.content" /> <--- this still makes it angry
 <KpiTransitTime v-if="kpi.type === 'transitTime'" :content="kpi.content" />
 <KpiInvoices v-if="kpi.type === 'invoices'" :content="kpi.content" />
</template>

CodePudding user response:

You would normally use a union which represents all valid states.

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