Consider the following example:
const assign = <T, K extends keyof T>(...args: T[]): T =>
args.reduce((result, current) =>
(Object.keys(current) as K[]).reduce((target, key) => {
target[key] = current[key];
return target;
}, result)
, args[0]);
class Base {
str1: string = '';
str2: string = '';
constructor(data: Partial<Base>) {
assign(this, data);
}
}
class Derived extends Base {
str3: string = '';
constructor(data: Partial<Derived>) {
super(data);
Object.assign(this, data);
}
}
const derivedObj = new Derived({ str1: 'text', str3: 'new prop' })
const baseObject = new Base(derivedObj);
console.log(baseObject);
// Outputs:
// Data { "str1": "text", "str2": "", "str3": "new prop" }
The base class comprises less properties than the derived class. The base class constructor accepts a Partial<Base>
which is also compatible with the Partial<Derived>
type. This results in extraneous properties being assigned to the base class object when passing an object of type Partial<Derived>
.
Is there a way to initialize the base class object only with its class-specific properties (str
and str2
and not str3
)?
PS: There are a lot of seemingly similar discussions on GitHub and here. So far, I haven't found any which tackles this exact problem.
This works:
const assign = <T, K extends keyof T>(...args: T[]): T =>
args.reduce((result, current) =>
(Object.keys(args[0]) as K[]).reduce((target, key) => {
if (current[key] !== undefined) target[key] = current[key];
return target;
}, result)
, args[0]);
See this playground