← Back
typescript

keyof typeof

Sometimes you have this kind of object in typescript:

const TASK_STATUS: Record<string, number> = {
notStarted: 0,
completed: 1,
inProgress: 2,
deleted: 3,
disabled: 4,
};

And you want a type that models that status. For example:

type TaskStatus =
| "notStarted"
| "completed"
| "inProgress"
| "deleted"
| "disabled";

The problem is to keep in sync the object and the type.

Before I've tried to use the keyof operator (don't try this at home):

// BAD
type TaskStatus = keyof TASK_STATUS;

but it raises an obscure error:

'TASK_STATUS' refers to a value, but is being used as a type here.ts (2749)

keyof #

The problem is that keyof only works with types.

What it means? This 👇

type Task = {
label: string;
priority: number;
};

// this is possible:
type TaskProperties = keyof Task;
// is the same as:
type TaskProperties = "label" | "priority";

Notice that keyof works with interfaces too.

Read more: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html#keyof-and-lookup-types

typeof #

Okey, then. Is any way to get the Type of an object. Yes, it is:

type TaskStatus = keyof typeof TASK_STATUS;

BONUS: as const #

In case you want the opposite (a type with values) you must use as const and a couple of TS tricks:

const STATUS_MAP = {
0: "notStarted",
1: "completed",
2: "inProgress",
3: "deleted",
4: "disabled",
} as const;

type NumericStatus = keyof typeof STATUS_MAP;
export type TaskStatus = typeof STATUS_MAP[NumericStatus];

Sources #