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;
}