简体   繁体   English

TypeScript - 如何将对象 A 的属性复制到扩展 A 的新对象 B 上 - 在旧 ts 版本上工作现已损坏

[英]TypeScript - how to copy object A's properties onto new object B that extends A - worked on older ts version now broken

I have a class B which extends A .我有一个extends AB类。 I am trying to copy A onto B (since B has all the same properties (and more) as A ).我正在尝试将A复制到B上(因为B具有与A相同的所有属性(以及更多属性))。

Example:例子:

class TypeA {
    propX: number = 0;
    propY: number = 0;
}

class TypeB extends TypeA {
    propZ: number = 0;
}

let A: TypeA = {propX: 1, propY: 2};
let B: TypeB = new TypeB();

//Here I want to copy A's properties onto B
Object.keys(A).forEach(prop => B[prop] = A[prop]);  //this how we did it on older version of typescript, still works in this example but won't compile in my new project

//now set B's non-shared property
B.propZ = 3;

//desired output {propX: 1, propY: 2, propZ: 3}
console.log(B);

That Ojbect.keys(A) ... line is how we did it on a project with an earlier TS version, but now it won't compile.Ojbect.keys(A) ...行是我们在具有较早 TS 版本的项目上所做的,但现在它不会编译。 In fact, in this TS fiddle it will successfully run with desired results.事实上,在这个 TS fiddle中,它将成功运行并获得预期的结果。 However, there are errors on that line.但是,该行有错误。 And in my Angular project, it simply won't compile at all.在我的 Angular 项目中,它根本无法编译。

How can/should I do this now?我现在可以/应该怎么做?

Also, yes I did look at this similar question , but did not find a working solution.另外,是的,我确实看过这个类似的问题,但没有找到可行的解决方案。 The accepted "solution" there does not appear correct to me, despite not understanding it, I tried implementing it to my example with:那里接受的“解决方案”对我来说似乎不正确,尽管我不理解它,但我尝试将它实施到我的示例中:

let key: keyof TypeA;
for (key in A) {
  A = {
    ...A,
    [key]: B[key]
  }
}

That really doesn't make much sense to me, but I tried it anyway before posting 🤷‍♂️这对我来说真的没有多大意义,但我还是在发帖前试过了🤷‍♂️

Thanks for your time.谢谢你的时间。

The old "hey compiler shut up I know what I'm doing".旧的“嘿编译器闭嘴我知道我在做什么”。

Object.keys(A).forEach((prop) => { (B as any)[prop] = (A as any)[prop]; });

or或者

Object.keys(A).forEach((prop) => { (<any>B)[prop] = (<any>A)[prop]; });

Some might say it's bad practice, but I think it's fine in this situation.有人可能会说这是不好的做法,但我认为在这种情况下没问题。

You can store your keys in a readonly array and iterate the keys when copying the values.您可以将键存储在只读数组中,并在复制值时迭代键。 You also use this array to constrain the shape of the base class when defining it:在定义基类时,您还可以使用此数组来约束基类的形状:

TS Playground TS游乐场

// Define the common keys in a readonly array:
const keysA = ['propX', 'propY'] as const;
type KeyA = typeof keysA[number];

// Define the base class using an "implements" clause to ensure that
// its shape includes the keys above:
class TypeA implements Record<KeyA, number> {
  propX: number = 0;
  propY: number = 0;
}

class TypeB extends TypeA {
  propZ: number = 0;
}

let A: TypeA = {propX: 1, propY: 2};
// Just a note: A is not an instance of TypeA since you did not construct it:
console.log({'A instanceof TypeA': A instanceof TypeA}); // false

let B: TypeB = new TypeB();

// This is ok because the keys are string literals in the readonly array:
for (const key of keysA) B[key] = A[key];

B.propZ = 3;

console.log({B}); // { propX: 1, propY: 2, propZ: 3 }

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

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