gpt4 book ai didi

typescript - 创建将为对象属性赋值的通用 TypeScript 函数

转载 作者:行者123 更新时间:2023-12-05 01:53:52 26 4
gpt4 key购买 nike

我想创建一个简单的函数,它将获取特定对象的 key 和相应键的 value 并将新值分配给对象。像这样:

interface MyObject {
key1: string
key2: number
}

const object: MyObject = {
key1: 'abc',
key2: 100
}

const updateObjectProperty = (key: keyof MyObject, value: MyObject[keyof MyObject]) => {
object[key] = value
}

但在这种情况下 - 它不起作用。 TypeScript 编译器显示错误:

Type 'string | number' is not assignable to type 'never'.

我觉得也许一些泛型可能会解决这里的问题,但我正在努力弄清楚如何解决。

最佳答案

如果使用泛型类型参数将参数绑定(bind)在一起,它将编译:

const updateObjectProperty = <K extends  keyof MyObject>(key: K, value: MyObject[K]) => {
object[key] = value
}

updateObjectProperty("key1", "") //ok
updateObjectProperty("key2", "") // err
updateObjectProperty("key2", 2) // ok

Playground Link

您的版本不起作用的原因是您可以传入不相关的键和值:

updateObjectProperty("key2", "") // key2 now has a string

Playground Link

现在我们的新版本也不是 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

Playground Link

您可以做与 TS 相同的事情,并将值键入为可能的属性值的交集,这也将捕获此漏洞,但这将需要在实现中再次断言:

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

Playground Link

关于typescript - 创建将为对象属性赋值的通用 TypeScript 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70957063/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com