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>
?
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"))