Reputation: 4081
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"]
.
Upvotes: 1
Views: 1605
Reputation: 327624
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
andset
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!
Upvotes: 2
Reputation: 25790
If I understand correctly, this is what you'd like:
type SpecialGenericType<T extends object> = {
[K in keyof T]: K
};
function proxify<T extends object>(source: T) {
const proxy = new Proxy(source, {
get: (_, property) => {
return property
}
});
return proxy as SpecialGenericType<T>;
}
const $ = proxify({
prop: {},
a: 'some',
b: 'random',
c: 'values',
} as const)
$.prop // typed as the literal value "prop"
const values = [
$.a,
$.b,
$.c
] as const
// values has the type (and value) ["a", "b", "c"];
Upvotes: 0