Typescript interface constants: you’re probably doing it wrong
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
.