Consider the following example data representing shops containing lists of pending and fulfilled purchase order ids:
{
"shop-45": {
"FULFILLED": [55, 70]
},
"shop-46: {
"PENDING": [59, 54]
"FULFILLED": [100, 101]
}
}
If a shop has neither pending nor fulfilled orders, it does not appear in the list at all.
I attempted to represent this using the following:
type Status = "PENDING" | "FULFILLED";
interface ShopList {
[shop: string]: {
[status in Status]: number[];
}
}
Unsurprisingly, tsc
complains when I do not have both PENDING
and FULFILLED
as sub-properties of a shop.
I quelled the error by making that property optional ([status in Status]?: number[]
) but I don't think that's really what I want to do, since a shop will never have zero sub-properties.
Another whimsical, shot-in-the-dark attempt [status in Partial<Status>]: number[];
complains similarly.
Is that my only option, and simply not something to worry about?
This is a trivialized MCVE; the real one is far more complex and has more layers. That's (always?) the motivation behind using generics rather than repeating every possible key name: the enum is used as field values in other objects.
TypeScript/issues references discussing similar-seeming situations: 7374 | 19211 | 14934 | 5683.
If you're looking to bar the scenario where a shop won't show up without either PENDING
or FULFILLED
you will need to be a little more explicit with your types. For instance, you could do the following:
type ShopWithPending = {
PENDING: number[];
}
type ShopWithFulfilled = {
FULFILLED: number[];
}
type ShopStatus = ShopWithPending | ShopWithFulfilled | (ShopWithPending & ShopWithFulfilled);
interface ShopList {
[shop: string]: ShopStatus
}
However, this does make it hard to then use shops
pulled out of the list, since Typescript will see the ShopStatus
type as something that is not guaranteed to have any properties and will thus not allow you to deference PENDING
or FULFILLED
.
In order to get back that ability, you will need something else on the Shop
types that allow Typescript to narrow back down the type inference to a specific typed version.