将属性从一个对象分配给另一个

时间:2020-09-04 20:35:56

标签: typescript

在将属性从一个对象复制到另一个对象时,如何让TypeScript理解所提供的键实际上属于目标对象?

interface Example {
  value: number
  dontUpdate: string
}

const a: Example = { value: 1, dontUpdate:  'a' }
const b: Example = { value: 2, dontUpdate: 'b' }

Object.keys(b).forEach(key => {
  if (key === 'dontUpdate') return
  a[key] = b[key]
  // ^ Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Example'.
})

for (let key in b) {
  if (key === 'dontUpdate') continue
  a[key] = b[key]
  // ^ Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Example'.
}

for (let key in b) {
  if (b.hasOwnProperty(key) && key !== 'dontUpdate') {
    a[key] = b[key]
    // ^ Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Example'.
  }
}

Playground

2 个答案:

答案 0 :(得分:0)

不保证对象仅具有您在界面中分配的键。接口通常是键的子集。

请记住,TypeScript被编译为JavaScript。接口在JavaScript中不存在。无论您的界面是什么样,对象上的任何键都会被复制。

这就是为什么您会收到此错误的原因。如果要复制特定的密钥,则必须对每个密钥进行测试。

if(key === 'value') a[key] = b[key] // no error

否则,您可以将它们强制转换为任何类型,并了解它不仅会复制界面中的键,还会复制对象上的所有键。

(a as any)[key] = (b as any)[key]

答案 1 :(得分:0)

如果只想让TypeScript编译器理解您正在访问该对象的属性,则可以使用keyof运算符 https://www.typescriptlang.org/docs/handbook/2/types-from-extraction.html#the-keyof-type-operator


如果要在两个不同的对象中访问相同的属性,要将一个属性复制到另一个对象中,则仍可以通过以下方式使用keyof运算符:

interface Example {
  value: number;
  dontUpdate: string;
  somethingElse: boolean;
}

const a: Example = { value: 1, dontUpdate:  'a', somethingElse: true }
const b: Example = { value: 2, dontUpdate: 'b', somethingElse: false }
const copyProp = <T extends keyof Example>(source: Example, target: Example, prop: T): void => {
  target[prop] = source[prop];
}

Object.keys(a).forEach((key) => {
  if (key === 'dontUpdate'){
    return;
  }

  // Copy the property key, from object 'a' to object 'b'
  copyProp(a, b, key as keyof Example);
})

console.log(b);

其中扩展keyof 表示从 keyof

获得的属性之一

如果只想将一个对象复制到另一个对象,则可以使用散布运算符:

const copy = {
   ...source
};

如果要复制没有特定属性的整个对象,则可以将散布运算符与解构运算符一起使用:

const { dontUpdate, ...copy } = source;