I want to create a helper type to infer the key used inside an indexed access type.
Example:
type X = { foo: string, bar: boolean }
type Fn = <T extends X>(value: T) => T["foo"]
type Helper<T> = ???
type Result = Helper<Fn> // should be "foo"
The approach I tried is similar to the built-in ReturnType
helper, but doesn't work so far:
type Helper<Fn> = Fn extends (value: infer T) => infer R
// R extends T[infer Key] does not work: Type 'Key' cannot be used to index type 'T'.
? R extends T[keyof T]
? T[keyof T]
: never
: never
Is this even possible?
You can achieve something reasonably close using a mapped type, but this requires you to know what T
is beforehand:
type Helper<T, Fn extends (...args: any[]) => any> = {
[K in keyof T]: T[K] extends ReturnType<Fn> ? K : never;
}[keyof T];
type Result = Helper<X, Fn>;
// ^? "foo"
However, a major drawback is that if X
has multiple keys with the same type,
type X = { foo: string; bar: boolean; baz: string };
then the result will include all of those keys:
type Result = Helper<X, Fn>;
// ^? "foo" | "baz"