Reputation: 2610
In the logic below I am trying to type the data that is coming as balanceModel parameter to the function but straggle a bit with the deep nested model and will appreciate a lot if somebody can point out the flaw in the types below.
Here is a live example of the logic below in codesandbox:
https://codesandbox.io/s/bold-meitner-vxto9
type BalanceModelAMDRType = {
from: number;
to: number;
[index: string]: number;
};
type BalanceModelSectionType = {
DRI: {
AI: number;
AMDR: BalanceModelAMDRType;
EAR: number;
RDA: number;
UL: number;
unit: string;
[index: string]: string | number | BalanceModelAMDRType;
};
};
type BalanceModelProgressSectionType = {
DRI: {
recommended: number;
unit: string;
[index: string]: string | number;
};
};
type BalanceModelType = {
energy: BalanceModelSectionType;
[index: string]: BalanceModelSectionType | BalanceModelProgressSectionType;
};
function _updateEnergyDependentSections(
balanceModel: BalanceModelType,
energy: number
): void {
const sections = [`mock`, `data`];
sections.forEach(sectionName => {
if (balanceModel[sectionName]) {
const { DRI } = balanceModel[sectionName];
Object.keys(DRI).forEach(DRIName => {
switch (true) {
case sectionName === `mock`:
const AMDR = DRI[DRIName];
Object.keys(AMDR).forEach(AMDRValueName => {
const AMDRValue = AMDR[AMDRValueName];
AMDR[AMDRValueName] = Math.round(
AMDRValue * conversionMultiplier
);
});
break;
case sectionName === `data`:
DRI[DRIName] = Math.round(DRI[DRIName] * conversionMultiplier);
}
});
}
});
}
Upvotes: 0
Views: 72
Reputation: 454
If I understood the problem correctly.
const AMDR = DRI[DRIName]
could be string | number | BalanceModelAMDRType
.
In mock
section you want it be BalanceModelAMDRType
and in data
as number.
if you know for a fact that it will always be in those type in that moment, you add as
type"
to end, like
const AMDR = DRI[DRIName] as BalanceModelAMDRType; or
const AMDR = DRI[DRIName] as number;
if you do not know for a fact that in those instances the value will be in those types, you need to use a type guard(if statement).
if(typeof AMDR !== 'number' or typeof AMDR !== 'string'){ // AMDR is BalanceModelAMDRType }
if(typeof AMDR == 'number'){ //AMDR is number }
You can add a property to a type
(interface), which will identify it as well, like:
type BalanceModelAMDRType = {
type: "AMDR";
from: number;
to: number;
} & { [index: string]: number };
and have a type guard function:
function isBalanceModelAMDRType(v: any): v is BalanceModelAMDRType {
return "type" in v && v.type === "AMDR";
}
Upvotes: 1