I have the following TypeScript code that attempts to replace the values of the properties of one class instance with the values of another using a loop.
class A {
n: number = 1
s: string = "hello"
}
const myA1 = new A()
const myA2 = new A()
myA2.n = 2
myA2.s = "hi"
for (const k of Object.keys(myA1)) {
/* Type 'string | number' is not assignable to type 'never'.
Type 'string' is not assignable to type 'never'. */
myA1[k as keyof A] = myA2[k as keyof A]
}
I know I could manually replace the properties like so:
myA1.n = myA2.n
myA1.s = myA2.s
However, I would like to replace them dynamically. Is there a way to tell TypeScript that I know the properties are of the same type? because they are (the same keys are being used for instances of the same class).
A follow-up question I also have is: what if the classes were different, but I also knew that their properties with the same name have the same type? Could the value replacement also be done in typescript?
I welcome any solutions or proposals following the same or another line of thought and logic. Avoiding things like type assertions would be fantastic.
Thank you
CodePudding user response:
You can do this via generics. Although, a cast is required for Object.entries(a)
because TS isn't smart enough to know it is (keyof typeof a)[]
which is just (keyof T)[]
. Here's your solution:
class A {
n: number = 1
s: string = "hello"
}
const myA1 = new A()
const myA2 = new A()
function copyProps<T>(a: T, b: T) {
for (const k of Object.keys(a) as (keyof T)[]) {
a[k] = b[k];
}
}
copyProps(myA1, myA2);
CodePudding user response:
It is possible to use Object.assign() method:
The Object.assign() method copies all enumerable own properties from one or more source objects to a target object. It returns the modified target object.
An example:
class A {
n: number = 1
s: string = "hello"
}
const myA1 = new A()
const myA2 = new A()
myA1.n = 1;
myA2.n = 2;
myA1.s = "s1"
myA2.s = "s2"
const assigned = Object.assign(myA1, myA2)
console.log(`assigned`, assigned)
console.log(`myA1`, myA1)
console.log(`myA2`, myA2)
Or you can use spread syntax:
class A {
n: number = 1
s: string = "hello"
}
const myA1 = new A()
const myA2 = new A()
myA1.n = 1;
myA2.n = 2;
myA1.s = "s1"
myA2.s = "s2"
const assigned = {...myA1, ...myA2};
console.log(`assigned`, assigned)
console.log(`myA1`, myA1)
console.log(`myA2`, myA2)