我遇到了一个关于在普通对象上设置键/值的问题。
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"))
代码真的很简单,而我得到错误:
Type '{ [x: string]: V; }' is not assignable to type 'Record<K, V>'.
为什么我会出现这个错误?我的意思是k有一个扩展字符串的类型k,所以我认为它们是相同的。如何得到正确的结果?
顺便说一句,getAObject("foo", "bar")
的类型显示Record<"foo",string>
,为什么不显示Record<"foo","bar">
或Record<string,string>
?
操场
如果不需要使用比字符串更精确的类型,我建议将键设置为string
。
type getAObjectFn = <V>(k: string, v: V) => Record<string, V>
const getAObject: getAObjectFn = (k, v) => {
return {
[k]: v
}
}
然而,如果你想要一个更精确的类型,你可以进行类型转换,在这种情况下应该是安全的。
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>
}
我的猜测是,您需要这样做的原因是[]
-运算符没有保留k
的类型(只是我的猜测(。通过执行类型转换,可以恢复键的类型。
此外,我猜测getAObject("foo", "bar")
返回Record<"foo",string>
的原因是类型K extends string
使编译器寻找比string
更具体的类型并找到类型"foo"
,而对于V
,它满足于string
。