I recently came across a small requirement while adding types to a particular component. Consider the following type
interface OrderDetails { createdDt: string; updatedDt: string; currentStatus: "Active" | "InActive" | "Deleted" }
I need to show a list of them in a paginated manner and also provide
filters to view a subset of them.
In this case, the filter would be on currentStatus
. The type
signature of my list was,
type List = { orders: OrderDetails[]; activeStatus: string; }
Naturally activeStatus
is kept as a string, but I'd like to
go one step further and see if I can make sure that
activeStatus
can only be one of
"Active" | "InActive" | "Deleted"
.
At this point, there are two approaches to solving this requirement. One
would be to create a new type for currentStatus
.
type OrderStatus = "Active" | "InActive" | "Deleted"; interface OrderDetails { createdDt: string; updatedDt: string; currentStatus: OrderStatus; } type List = { orders: OrderDetails[]; activeStatus: OrderStatus; }
The above solution works wonderfully well if OrderDetails
was
a self-defined type but in this case, this came from a dependency that I
had little control over.
The other approach is to extract the type of
OrderDetails.currentStatus
and assign it wherever needed.
interface OrderDetails { createdDt: string; updatedDt: string; currentStatus: "Active" | "InActive" | "Deleted"; } type List = { orders: OrderDetails[]; activeStatus: OrderDetails.currentStatus; }
On surface this sounds like it would work, but sadly Typescript bugs out.
I haven't fully investigated the reason,
but an educated guess is that this collides with parsing of
Namespace.Type
and hence TS disallows accessing members here.
So then, what next?
Thankfully, Typescript understands what I'm trying to do and shows an helpful error message
Cannot access 'OrderDetails.currentStatus' because 'OrderDetails'
is a type, but not a namespace. Did you mean to retrieve the type of the
property 'currentStatus' in 'OrderDetails' with
'OrderDetails["currentStatus"]'?
Once you apply the suggested fix,
interface OrderDetails { createdDt: string; updatedDt: string; currentStatus: "Active" | "InActive" | "Deleted"; } type List = { orders: OrderDetails[]; activeStatus: OrderDetails["currentStatus"]; }
Now with this, I am confident that I won't end up with a wrong value or a
typo when using activeStatus
.
You can play around the code shown here on the Typescript Playground.