I have some data which looks like this –
{
System: 'VIT0056',
Value: {
Start: 3.3,
End: 3.9
},
'Initial Range' : {
'Start': '1/12/2022',
'End': '31/12/2022',
},
Manager: 'Karl Woods',
Location: 'Tokyo',
Price: '$1.50',
},
I am currently mapping over this object like so –
{Object.entries(data).map(([key, val]) => {
if (key === 'Value') {
return (
<S.ValueContainer key={key}>
<Label>{key}:</Label>
<Text size="small">** DO SOMETHING HERE TO SHOW VALUES **</Text>
</S.ValueContainer>
)
}
if (key === 'Initial Range') {
return (
<S.ValueContainer key={key}>
<Label>{key}:</Label>
<Text size="small">** DO SOMETHING HERE TO SHOW VALUES ** </Text>
</S.ValueContainer>
)
}
return (
<S.ValueContainer key={key}>
<Label>{key}:</Label>
<Text size="small">{val}</Text>
</S.ValueContainer>
)
}
)
}
For the Value and Initial Range keys I want to be able to show them like this –
Value : 3.3 – 3.9
Initial Range: From 01 Dec 2022 To 31 Dec 2022
However I am having trouble accessing the values due to the fact that they are nested objects.
When I put them inside the if statement and try to do val.Start it tells me that –
Property ‘Start’ does not exist on type ‘string | Range’.
But I know that the value I’ll be accessing in this block will only be of type Range. Is there a way to define this?
>Solution :
You can use a type assertion to tell your compiler, that the value actually is a Range
<Text size="small">{(val as Range).Start} - {(val as Range).End}</Text>
or you can implement a ToString(value: string | Range) function
function ToString(value: string | Range) {
//if value is a string, just return the value
if (typeof value === "string") return value;
//here the compiler knows it must be a Range
//because it's not a string ...
return `${value.Start} - ${value.End}`;
}
and use this in your rendering
<Text size="small">{ToString(val)}</Text>
Furthermore, you seem to have different types of ranges also. So when using the ToString() approach, you might also need to do a typecheck on your start and end properties
function ToString(value: string | Range) {
if (typeof value === "string") return value;
if (typeof value.Start === "number")
return `${value.Start} - ${value.End}`;
//here you know value is a range and
//the properties of range are strings
//(given both always have the same type
//or apply appropriate formatting for your dates
return `${value.Start} to ${value.End}`;
}
Of course you can also return some renderings instead of only strings. As in the following example
function ToRender(value: string | Range) {
//if value is a string, just return the value
if (typeof value === "string") return (<div>{value}</div>);
//here the compiler knows it must be a Range
//because it's not a string ...
return (<div><span>{value.Start}</span> to <span>{value.End}</span></div>)
}