Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to define return type using keyof accessor with TypeScript?

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?

like image 378
Reactgular Avatar asked Oct 22 '25 19:10

Reactgular


1 Answers

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

like image 58
jcalz Avatar answered Oct 24 '25 09:10

jcalz