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

typescript - Error getting the type of key whilst mapping a collection - Stack Overflow

programmeradmin4浏览0评论

Some context: I am mapping a collection of objects, with the intention to pick the values of one member from that object.

type RadioOption = {
  value: string
  label: string
}

const requestTypeOptions = [
  { value: "question", label: "I have a question" },
  { value: "problem", label: "I have a problem" },
  { value: "complaint", label: "I have a complaint" },
] as const satisfies RadioOption[];

function pickKeyValue<C extends {[k: string]: any}[], K extends keyof C[number]>(collection: C, pick: K) {
  return collection.map((obj, i) => {
    return obj[pick]
    //         ^^^^    <- error
  }) as { [I in keyof C]: C[I][K] };
}

const pickedValues = pickKeyValue(requestTypeOptions, 'value')
// pickedValues: ["question", "problem", "complaint"]

The compiler returns the expected type for pickedValues, but there still is an error in the function itself.

It turns out that pick is of type string | number | symbol, which can not be used to index {[k: string]: any}.

edit: I understand now that {[k: string]: any} does not restrict the key to only be string (thanks jcalz).

But how do I make it so that pick is only of type string, so that it works as intended?

Playground

Some context: I am mapping a collection of objects, with the intention to pick the values of one member from that object.

type RadioOption = {
  value: string
  label: string
}

const requestTypeOptions = [
  { value: "question", label: "I have a question" },
  { value: "problem", label: "I have a problem" },
  { value: "complaint", label: "I have a complaint" },
] as const satisfies RadioOption[];

function pickKeyValue<C extends {[k: string]: any}[], K extends keyof C[number]>(collection: C, pick: K) {
  return collection.map((obj, i) => {
    return obj[pick]
    //         ^^^^    <- error
  }) as { [I in keyof C]: C[I][K] };
}

const pickedValues = pickKeyValue(requestTypeOptions, 'value')
// pickedValues: ["question", "problem", "complaint"]

The compiler returns the expected type for pickedValues, but there still is an error in the function itself.

It turns out that pick is of type string | number | symbol, which can not be used to index {[k: string]: any}.

edit: I understand now that {[k: string]: any} does not restrict the key to only be string (thanks jcalz).

But how do I make it so that pick is only of type string, so that it works as intended?

Playground

Share Improve this question edited yesterday publicJorn asked Feb 16 at 18:23 publicJornpublicJorn 2,4941 gold badge22 silver badges32 bronze badges 7
  • Please edit this to ask a single primary question, or it risks being closed with "Needs more focus: This question currently includes multiple questions in one. It should focus on one problem only." – jcalz Commented Feb 16 at 18:59
  • Thanks for the tip @jcalz, I have updated it to a singular question. – publicJorn Commented Feb 17 at 10:27
  • • Now the title has very little to do with the question you're asking. Could you edit to make them match up? • Note that the type {[k: string]: any} does not mean that only string keys can appear; types only enable keys, they don't prohibit unmentioned keys. So C extends {[k: string]: any}[] can have elements with all kinds of keys, including number and symbol. That's why you're seeing the error (but you didn't ask that, so this is mostly a helpful aside) – jcalz Commented Feb 17 at 12:16
  • Please check whether this meets your requirements – captain-yossarian from Ukraine Commented Feb 17 at 17:08
  • Thanks for the attempt yossarian! Your solution works, but it is very specific to the object in question. I want the function pickKeyValue to be smart enough to return an array where an arbitray collection of objects is given and we pick all values of given key. – publicJorn Commented yesterday
 |  Show 2 more comments

2 Answers 2

Reset to default 1

You could utilize 2 hacks here:

  1. add & string to K to ensure [Key: string] accepts it
  2. move the return type to as against the map function (sorry, the map function should be casted anyway):

Playground

function pickValue<C extends {[key: string]: any }[], K extends keyof C[number] & string>(collection: C, pick: K) {
  return collection.map((obj, i) => {
    console.log(pick)
    return obj[pick]
  }) as { [I in keyof C]: C[I][K] };
}

I tried to use your code and I think your problem is when you used as try to use this example and it's will help you

type RadioOption = {
    value: string;
    label: string;
  };

  const requestTypeOptions: Array<RadioOption> = [
    { value: "question", label: "I have a question" },
    { value: "problem", label: "I have a problem" },
    { value: "complaint", label: "I have a complaint" },
  ];

  const allValues = requestTypeOptions.map((c) => c.value);
  console.log(allValues);
发布评论

评论列表(0)

  1. 暂无评论