Is it possible to create a function that uses keyof to access a property of an object, and have TypeScript infer the return value?
interface Example {
name: string;
handles: number;
}
function get(n: keyof Example) {
const x: Example = {name: 'House', handles: 8};
return x[n];
}
function put(value: string) {
}
put(get("name"));
// ^^^ Error: Argument of type 'string | number' is not assignable to parameter of type 'string'
TypeScript is merging all the allowed types together, but when the function is called with the value "name" it does not infer the type is string.
I can resolve the issue by casting the type.
put(get("name") as string);
Is there a way to do this without casting?
Sure, you just have to make get generic so that it doesn't return the union of all possible output types:
function get<K extends keyof Example>(n: K) {
const x: Example = { name: "House", handles: 8 };
return x[n];
}
Now the signature is inferred to be:
// function get<K extends "name" | "handles">(n: K): Example[K]
Where the return type, Example[K], is a lookup type representing the type you get when you index into an Example with key K.
When you call it, K is inferred to be a string literal type if it can be:
get("name"); // function get<"name">(n: "name"): string
And Example["name"] is equivalent to string. So now your call works as desired:
put(get("name")); // okay
Hope that helps. Good luck!
Link to code
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With