Search code examples
typescripttypescript-genericsconditional-typesmapped-types

TypeScript type for object whose values match its keys


Is it possible to define a TypeScript type for an object where the key values are the literal key names themselves? For example:

declare const $: SpecialGenericType

$.prop // typed as the literal value "prop"

const values = [
  $.a,
  $.b,
  $.c
] as const

// values has the type (and value) ["a", "b", "c"]

The $ object could be implemented using a Proxy, but I'm not sure how to implement the SpecialGenericType. The type would need to allow any string as a key, but the values would need to be typed as the string literal of its key name (so Record<string, string> does not work in this case). For example, values above would have the tuple type ["a", "b", "c"].


Solution

  • What you're looking for is not currently possible in TypeScript. It works if you have some finite union of string literal keys, but not for all of string. There is an open suggestion at microsoft/TypeScript#22509 asking for this exact thing (called Thing instead of SpecialGenericType in the description), but there hasn't been any movement. The chief language architect said

    This really is a request to add compiler support for ECMAScript proxy objects, i.e. compiler knowledge of the relationship between property access operations and the get and set proxy methods. It is simply not possible to model that with our current type system features (because nothing allows you to capture the literal type corresponding to the property name in a property access).

    You might want to go to that issue and give it a 👍 or describe why you think your use case is compelling, but I doubt that it will be implemented anytime soon. Oh well, at least there's something like a definitive answer to this question, even if it is "no". Good luck!