Reputation: 41929
There is a question on SO about creating an array with different types, but I want to create an array with multiple complex types. The answer in the linked to question recommends using a union type, but I don't think that will suffice for a complex type, as typescript documentation says
If we have a value that has a union type, we can only access members that are common to all types in the union.
I want to create an array of Reports. However some of the reports have different properties from each other, and also several in common. I'm worried if I create it as below then somewhere in the code I might not be able to access the different properties on the subreports.
What's the recommended way to create an array of complex types in Typescript?
interface Reports extends Array<Report>{}
interface Report {
id: number;
timestamp: number;
type: string;
subreport: SubReportA | SubReportB | SubReportC
}
interface SubReportA {
values: []
}
interface SubReportB {
random_property: number;
other_random_name: number;
}
interface SubReportC{
values: [];
name: string;
}
Upvotes: 2
Views: 1111
Reputation: 29983
That would be a use case for discriminated unions. First, we need a base interface for all kinds of sub-reports. I will also be adding a discriminating field kind
that can only assume specific values known in compile time "A", "B" and "C".
interface SubReport {
kind: "A" | "B" | "C";
}
At this point, we can make our interfaces specify one string literal each:
interface SubReportA {
kind: "A";
values: []
}
interface SubReportB {
kind: "B";
random_property: number;
other_random_name: number;
}
interface SubReportC{
kind: "C";
values: [];
name: string;
}
The same reasoning could be applied to the original Report
type if need be. I'm not sure whether the report's "type" field is supposed to be a discriminator, but it can be moved to the subreport object if it is.
Also, as explained in the link above, discriminated unions allow you to retrieve specific fields once you test on the discriminator.
if (subreport.kind === 'B') {
console.log(subreport.random_property);
}
Upvotes: 3