javascript - 如何仅将对象属性子集的值复制到 TypeScript 中的另一个现有对象

标签 javascript typescript object ecmascript-6 ecmascript-2020

假设我有一个现有对象 obj1 = {a: 'A', b: 'B', c: 'C', d: 'D'}

我有另一个对象,如 obj2 = {b: 'B2', c: 'C2', d: 'D2', e: 'E2'}

现在我想有选择地仅将少数属性的值从 obj2 复制到 obj1,对于 obj1 中的其余属性,我希望它们不变。

现在,假设我想复制属性 bd 的值。我想做类似的事情

obj1 = {a: 'A', b: 'B', c: 'C', d: 'D'};
obj2 = {b: 'B2', c: 'C2', d: 'D2', e: 'E2'};

copyPropertyvalues(
    obj2, // source
    obj1, // destination
    [obj2.b, obj2.d] // properties to copy >> see clarification below
); // should result in obj1 = {a: 'A', b: 'B2', c: 'C', d: 'D2'}

这个方法怎么写?请注意,我也不想以字符串形式提供属性列表,因为我希望编译时尽可能安全。

这里的基本问题是:

  1. 仅复制对象中的几个属性值
  2. 复制到现有对象而不创建新对象
  3. 保留目标对象中的其他属性值
  4. 避免使用字符串作为属性名称(如 'b'、'd')并尽可能利用 TypeScript 安全性

基于评论的澄清:

当我在(伪)代码示例中说obj2.b 左右

  • 我不是字面上的意思 obj2.b
  • 而是一些在编译时检查 b 实际上是 obj2 类型的属性

最佳答案

我对 copyPropertyvalues() 的建议会是这样的:

function copyPropertyvalues<T, K extends keyof T>(s: Pick<T, K>, d: T, ks: K[]) {
    ks.forEach(k => d[k] = s[k]);
    return d;
}

函数是generic在类型 T目标对象的类型,以及类型 K您要从源对象复制到目标对象的键名。我假设您想要要求从源复制的属性应该与目标中已有的属性具有相同的类型;例如,您不会复制 "a"来自类型来源的属性 {a: number}到类型为 {a: string} 的目的地,因为你会写一个 numberstring并违反了目的地的类型。

请注意,我们不需要源对象正好是 T ;它只需要同意 TK 中的所有键.即我们只说一定是Pick<T, K>使用 the Pick<T, K> utility type .

请注意,我们肯定传递了一个键字符串数组,编译器将其推断为不只是 string。 , 但特别是 union字符串 literal types这是 keyof T 的子集(使用 the keyof type operator 获取 T 的已知键的并集)。所以如果你传入 ["b", "d"] , 编译器将推断其为 Array<"b" | "d"> 类型而不仅仅是 Array<string> .这将为您提供您正在寻找的类型安全性,而无需担心 nameof 之类的问题。它在 JavaScript 中不存在(并且在它存在之前不会存在于 TypeScript 中,请参阅 microsoft/TypeScript#1579 )。


好吧,让我们试试看:

copyPropertyvalues(
    obj2, // source
    obj1, // destination
    ["b", "d"] // properties to copy
);
console.log(obj1)
/* {
  "a": "A",
  "b": "B2",
  "c": "C",
  "d": "D2"
}  */

看起来它的行为符合您的要求。如果你把错误的键放在那里,你会得到编译时错误:

copyPropertyvalues(
    obj2, // error!
    obj1,
    ["a"]
)

copyPropertyvalues(
    obj2,// error!
    obj1,
    ["z"]
)

Playground link to code

关于javascript - 如何仅将对象属性子集的值复制到 TypeScript 中的另一个现有对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69993223/

相关文章:

javascript - '弃用警告 : Collection#find: pass a function instead'

typescript - 为不同的枚举定义特定的对象负载

Javascript Promise 调用一个 Promise 混淆

JavaScript indexOf() 对于数组中已识别的对象返回 -1

javascript - 如何执行一个函数,其详细信息在另一个函数中作为参数传递

javascript - 如何使用 AJAX 显示结果

javascript - jquery:避免过多的递归

Javascript - 使用数组作为对象名称,然后使用循环获取属性

typescript - 找不到模块 '@foundry/ontology-api' 或其相应的类型声明

javascript - 返回对象数组