There is an open issue at microsoft/TypeScript#25214 requesting the ability to annotate the type of the values of an object, while allowing the compiler to somehow infer the keys. For now there is no direct support for this; and the issue is marked as "needs proposal", meaning that it's not clear how such a feature would work. If you're really interested in seeing this happen, you could give that issue a 👍 and possibly suggest how it would work.
For now, though, you can get indirect support for this via a generic identity helper function:
const asGestures = <K extends PropertyKey>(
gestures: { [P in K]: Direction[] }) => gestures;
Instead of annotating or asserting that each property of your object literal is a Direction[], you call asGestures() on the "plain" object literal. The compiler will constrain the type of the object to something whose values are of type Direction[], and whose keys are of type a key-like type K it infers:
const gestures = asGestures({
newSubThought: ['r', 'd', 'r'],
newThought: ['r', 'd'],
clearThought: ['l', 'r']
//...
})
/* const gestures: {
newSubThought: Direction[];
newThought: Direction[];
clearThought: Direction[];
} */
Even better, if you make a mistake in your array, the compiler will notice and catch it for you:
const badGestures = asGestures({
begoneThought: ['r', 'u', 'd', 'e'], // error!
// --------------------------> ~~~
// Type '"e"' is not assignable to type 'Direction'.
})
whereas type assertions using as will tend to suppress such errors (one major use of type assertions is to narrow types past what the compiler can verify):
['r', 'u', 'd', 'e'] as Direction[] // no error
Playground link to code
stringis wider thanDirection, andstring[]is wider thanDirection[](you can assign aDirection[]value to a variable of typestring[]but not vice versa)as constwhich creates narrow values. Updated.