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

标签 typescript generics typescript-typings

我想创建一个简单的函数,它将获取特定对象的 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/

相关文章:

angular - 按下(单击)按钮时调用 (ngSubmit)

javascript - 纯 Javascript 中的 Angular 2 路由(无 Typescript)

java - 创建抽象通用 jaxb 类

Typescript 泛型,正在使用的关键,但它也使用符号 | 进行计算数量 |字符串也是如此

angular - 调整 ng2-charts 的宽度和高度

scala - 为什么 deriveHCons 的签名在 Symbol 是最终类时声明 `HK <: Symbol`

Java 通配符读写权限

typescript - 为任意对象属性声明 Typescript 类型

angular7 - Angular 7 中的 declarations.d.ts

javascript - 类型 '{}' 无法分配给类型 'Readonly<IIdeasContainerProps>' 类型 '...' 中缺少属性 '{}'