The function getValue
returns a type that is manually set to MyInterface[typeof key]
. However, even without this manual setting, TypeScript automatically infers it to be typeof object[key]
, which is equivalent to MyInterface[keyof MyInterface]
since typeof key
is the same as keyof MyInterface
.
MyInterface[keyof MyInterface]
represents an indexed access type, creating a union of all property types accessed by the keys in type keyof MyInterface
. As explained in patrickhrastnik's response, keyof MyInterface
itself is a union of all keys in MyInterface
, namely 'a' | 'b'
. Thus, MyInterface['a' | 'b']
results in Something | SomethingElse
.
TypeScript conducts static type analysis only, and therefore deduces the narrowest return type based on the information available, such as the function parameter type being keyof MyInterface
.
To achieve a more specific return type, we must constrain the type of key
. Nonetheless, we still desire the ability to call getValue
with any key from MyInterface
.
An effective solution involves leveraging generic function argument type inference to allow TypeScript to deduce the type of key
parameter when the function is invoked; at that point, a more precise type can be inferred instead of the union of all keyof
types. By appropriately constraining the generic parameter type, we can still accept any of these keys as valid argument types:
const getValue2 = <T extends keyof MyInterface>(key: T) => {
// (key: T) => MyInterface[T]
const value = object[key];
return value;
}
Using generics in this function enables TypeScript to infer a more precise return type for each invocation:
const value2 = getValue2('a');
// Something
const value2b = getValue2('b');
// SomethingElse
Playground Link