Let's consider a basic scenario where we have a simple type that represents a key of a Thing
:
type ThingKey = "a" | "b" | "c"
We want to create an entry with some metadata for each value in order to iterate over it or use it as a map:
interface Thing {
key: ThingKey
stuff: string
moreStuff: number
}
const things: Thing[] = [
{
key: "a",
stuff: "AAA",
moreStuff: 42,
},
{
key: "b",
stuff: "BBB",
moreStuff: 43,
},
{
key: "c",
stuff: "CCC",
moreStuff: 44,
},
]
const thingByKey = _.keyBy(things, thing => thing.key);
Everything seems fine so far, but TypeScript doesn't ensure that our array contains entries for all possible values of ThingKey
. We need to guarantee that there is exactly one entry in things
for each value in the ThingKey
type. How can we accomplish this?
An alternative approach would be to define a map initially and then convert it into an array. However, this method involves mentioning the same key twice, leading to data redundancy and the possibility of creating inconsistencies between the keys within the object and the Thing itself.
export const alternativeThingByKey: Record<ThingKey, Thing> = {
a: {
key: "a",
stuff: "AAA",
moreStuff: 42,
},
b: {
key: "b",
stuff: "BBB",
moreStuff: 43,
},
c: {
key: "b", // <-- whoops
stuff: "CCC",
moreStuff: 44,
},
}
export const alternativeThings = Object.values(alternativeThingByKey)