最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to define return type using keyof accessor with TypeScript? - Stack Overflow

programmeradmin2浏览0评论

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?

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?

Share Improve this question asked Sep 11, 2019 at 18:12 ReactgularReactgular 54.9k24 gold badges173 silver badges218 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 12

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

发布评论

评论列表(0)

  1. 暂无评论