Typescript interface constants: you’re probably doing it wrong

Tamás Polgár
Developer rants
Published in
1 min readMay 9, 2024

I see this amateur mistake all the time. An interface definition, which is supposed to restrict allowed values to a set of predefined constants, is defined like this:

const CAT = 'meow';
const DOG = 'woof';
const COW = 'moo';

interface Animal {
name: string;
sound: typeof CAT | typeof DOG | typeof COW;
}

This isn’t going to work. The restriction would allow a totally invalid value, as long as it’s a string:

const myAnimal: Animal = {
name: 'Fluffy',
sound: 'Totally invalid value'
}

This is because typeof CAT refers to the type of the CAT constant, which is a string. So does typeof DOG and typeof COW. If any of these constants weren’t a string, then it would allow another type for sound.

The solution is to turn the constants into constant literals. Just add as const after their definitions:

const CAT = 'meow' as const;
const DOG = 'woof' as const;
const COW = 'moo' as const;

interface Animal {
name: string;
sound: typeof CAT | typeof DOG | typeof COW;
}

Now you indicated it to Typescript that CAT, DOG and COW are not merely strings, but string literals, and therefore not only their types, but their values also matter. And now an Animal type will only accept one of these values for sound.

--

--