繁体   English   中英

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

[英]How to copy values of only a subset of object properties to another existing object in TypeScript

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

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

现在我想选择性地从只有几个属性的值复制obj2obj1中,对于性能的休息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;
}

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

请注意,我们不需要源对象正好是T 它只需要在K中的所有键上与T一致。 也就是说,我们只说它必须是Pick<T, K>使用Pick<T, K>实用程序类型

并注意我们肯定是通过在关键字符串数组,该编译器会推断出不一样string ,而是专门为工会字符串字面类型它们的子集keyof T (使用keyof型运营商获得工会T的已知键)。 因此,如果您传入["b", "d"] ,编译器会推断它的类型为Array<"b" | "d"> Array<"b" | "d">而不仅仅是Array<string> 这将为您提供您正在寻找的类型安全性,而无需担心诸如nameof类的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 链接到代码

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM