如果使用泛型类型参数将参数绑定在一起,它将编译:
const updateObjectProperty = <K extends keyof MyObject>(key: K, value: MyObject[K]) => {
object[key] = value
}
updateObjectProperty("key1", "") //ok
updateObjectProperty("key2", "") // err
updateObjectProperty("key2", 2) // ok
游乐场链接
您的版本不起作用的原因是您可以传递不相关的键和值:
updateObjectProperty("key2", "") // key2 now has a string
游乐场链接
现在我们的新版本也不是100%安全,你可以这样调用它key
union,但这种情况不太常见:
let k: keyof MyObject = Math.random() > 0.5 ? "key1" : "key2"
let v: MyObject[keyof MyObject] = Math.random() > 0.5 ? 0 : "key2"
updateObjectProperty(k, v); // fails when key and value are mssmatched
游乐场链接
您可以执行与 TS 相同的操作,并将 value 作为可能的属性值的交集键入,这也将捕获此漏洞,但这将需要在实现中再次断言:
type ValueIntersectionByKeyUnion<T, TKey extends keyof T> = {
[P in TKey]: (k: T[P])=>void
} [TKey] extends ((k: infer I)=>void) ? I : never
const updateObjectProperty = <K extends keyof MyObject>(key: K, value: ValueIntersectionByKeyUnion<MyObject, K>) => {
object[key] = value as MyObject[K];
}
let k: keyof MyObject = Math.random() > 0.5 ? "key1" : "key2"
let v: MyObject[keyof MyObject] = Math.random() > 0.5 ? 0 : "key2"
updateObjectProperty(k, v); //err
updateObjectProperty("key1", "") //ok
updateObjectProperty("key2", "") // err
updateObjectProperty("key2", 2) // ok
游乐场链接