Home > OS >  TypeScript how to set key value on a object
TypeScript how to set key value on a object

Time:03-31

I got a problem about set key/value on a plain object.

type getAObjectFn = <K extends string, V>(k: K, v: V) => Record<K, V>

const getAObject: getAObjectFn = (k, v) => {
  return {
    [k]: v
  }
}

console.log(getAObject("foo", "bar"))

code is really simple while I got error:

Type '{ [x: string]: V; }' is not assignable to type 'Record<K, V>'.

why I got this error? I mean k has type K which extends string, so I think they are same.how to get correct result?

BTW, the type of getAObject("foo", "bar") shows Record<"foo",string>,why not Record<"foo","bar"> or Record<string,string>?

playground

CodePudding user response:

If you don't need to use a more precise type than string I would suggest setting the key to string.

type getAObjectFn = <V>(k: string, v: V) => Record<string, V>

const getAObject: getAObjectFn = (k, v) => {
  return {
    [k]: v
  }
}

However if you want a more precise type you could do a typecast, it should be safe in this scenario.

type getAObjectFn = <K extends string, V>(k: K, v: V) => Record<K, V>

const getAObject: getAObjectFn = (k, v) => {
  return {
    [k]: v
  } as Record<typeof k, typeof v>
}

My guess is that the reason you need to do this is that []-operator doesn't preserve the type of k (just my guess however). By doing the type cast you restore the type of the key.

Further on I'm guessing that the reason that getAObject("foo", "bar") returns a Record<"foo",string> is that the type K extends string makes the compilator look for a more specific type than string and finds the type "foo", while for V it is satisfied with string.

CodePudding user response:

Is there a reason for the complicated setup? You could just keep it simple with:

type getAObjectFn = (k: string, v: any) => { [x: string]: any; }

const getAObject: getAObjectFn = (k, v) => {
  return {
    [k]: v
  }
}

console.log(getAObject("foo", "bar"))
  • Related