1
votes

Suppose I have the following:

const myObj = { foo: 'cat', bar: 'dog', baz: 'bird' } as const;

type MyValue = 'fish' | 'bear' | 'cow';

const myValueMap: Record<string, MyValue> = {
  [myObj.foo]: 'fish',
  [myObj.bar]: 'cow',
} as const;

Because myValueMap is declared as an object with arbitrary string keys, we don't get type-checking on the actual keys of the object (cat and dog). I could remove the explicit declaration altogether, but then I don't enforce that the values are MyValues. (In my actual code, MyValue is several hundred constants strings.)

Is there a way, preferably without using a wrapper function, to enforce that values are MyValues and still maintain the property type-checking?

TS Playground

2

2 Answers

0
votes

Maybe make use of more generics -

const myValueMap: Record<myObj[keyof myObj], MyValue> = {
  [myObj.foo]: 'fish',
  [myObj.bar]: 'cow',
};
0
votes

If I understood you correctly, that's how you can achieve what you require:

const myObj = { foo: 'cat', bar: 'dog', baz: 'bird' } as const;

type MyValue = 'fish' | 'bear' | 'cow';

const myObjValue = myObj["" as keyof typeof myObj];

const myMap: Partial<Record<typeof myObjValue, MyValue>> = {
  [myObj.foo]: 'fish',
  [myObj.bar]: 'cow',
} as const;