Issue
There’s this type already available:
type GeometryFeature = {
type: "Feature";
properties: {
id: string;
refId: string | null;
rootZoneId: string;
name: string;
description: string | null;
startAt: string | null;
endAt: string | null;
createdAt: string;
updatedAt: string;
};
}
I would like to add a few more properties, let’s say these two: fill
of type string
, fillOpacity
of type number
by extending the GeometryFeature
type. But I would not like to avoid modifying the existing code. The idea behind these two params is to add colour. So I guess, the new type that would include colour related props could be called GeometryFeatureColored
.
How would you extend the GeometryFeature
turning it into GeometryFeatureColored
?
The GeometryFeatureColored
is expected to look like this:
type GeometryFeatureColored = {
type: "Feature";
properties: {
id: string;
refId: string | null;
rootZoneId: string;
name: string;
description: string | null;
startAt: string | null;
endAt: string | null;
createdAt: string;
updatedAt: string;
fill: string;
fillOpacity: number;
};
}
Preferably, I’d like to know what is the least verbose way of defining this type.
Solution
Probably the least verbose way to write this would be something like
interface GeometryFeatureColored extends GeometryFeature {
properties: GeometryFeature['properties'] &
{ fill: number, fillOpacity: number }
}
Since your GeometryFeature
interface’s properties
member is of an anonymous type and is not a named interface, you need to use the indexed access type GeometryFeature['properties']
to refer to it. Then you can intersect it with the object type containing the properties you wish to add.
Let’s test that it works as expected:
declare const gfc: GeometryFeatureColored;
gfc.properties;
/* (property) GeometryFeatureColored.properties: {
id: string;
refId: string | null;
rootZoneId: string;
name: string;
description: string | null;
startAt: string | null;
endAt: string | null;
createdAt: string;
updatedAt: string;
} & {
fill: number;
fillOpacity: number;
} */
gfc.properties.fill.toFixed(); // okay
gfc.properties.name.toUpperCase(); // okay
Looks good.
Note that you could also write
type GeometryFeatureColored = GeometryFeature & {
properties: { fill: number, fillOpacity: number }
};
which is even shorter, but intersecting at the top level is not completely identical to intersecting in a nested level. That is, {a: X & Y}
is similar to but observably different from {a: X} & {a: Y}
, and I believe you are asking for the former and not the latter. But I present it as an option in case terseness trumps all other concerns.
Personally I prefer to have named interfaces to refer to instead of intersections, since interfaces are more complex when viewed with IntelliSense:
type GeometryFeatureProperties = GeometryFeature['properties'];
interface GeometryFeatureColoredProperties extends GeometryFeatureProperties {
fill: number, fillOpacity: number
}
interface GeometryFeatureColored extends GeometryFeature {
properties: GeometryFeatureColoredProperties
}
As you can see, this is more verbose up-front, but is terser when you start using it (compare to the GeometryFeatureColored.properties
IntelliSense info above):
declare const gfc: GeometryFeatureColored;
gfc.properties;
// (property) GeometryFeatureColored.properties: GeometryFeatureColoredProperties
Answered By – jcalz
This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0