String Literal Types from Objects

1min read
Tags: TypeScript

Scenario:

We have a constant array of objects that all share the same interface. Based on these objects, we want to create a string literal type that holds all given values for a specific attribute. In the given example, we want to create a type that only allows the values Alice and Bob:

const arr = [
    { id: 1, name: 'Alice' },
    { id: 2, name: 'Bob' }
] as const;

type Name = typeof arr[number]['name'];

// Ok
const name1: Name = 'Alice';

// Error: Type '"Eve"' is not assignable to type '"Alice" | "Bob"'
const name2 : Name = 'Eve';

Similar scenario:

Instead of an array, we now have only one constant object and we would like to create a string literal type that holds all keys of its attributes. Unfortunately, this is not as trivial to solve like in our first scenario. However, we can create the same type if we introduce an intermediate step with a helper function:

const obj = {
    'Alice': {
        id: 1,
    },
    'Bob': {
        id: 2
    }
} as const;

function helperFn<T extends {[key: string]: any}>(t: T) {
    return t;
}
const typedObj = helperFn(obj);

type Name = keyof typeof typedObj;

// Ok
const name1: Name = 'Alice';

// Error: Type '"Eve"' is not assignable to type '"Alice" | "Bob"'
const name2 : Name = 'Eve';
Next.js
Mantine
Vercel