Md Faizaan


Written and published on 15th Feb, 2021

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.

Back