Does TypeScript
support copy-constructor (like for example C++ does)?
When the answer is no (or not yet), then what is the best practice to initialize our base-class (which we extend), and copy from an existing instance (of the same base-class type).
I tried but got error:
Multiple constructor implementations are not allowed
Currently our code uses the manually declared copy()
method of our base-class which does require the base-class to be already initialized,
But our base-class (ShopConfig) has some rather expensive operations in its constructor, which are already done once, and would not be required if there was a copy-constructor concept in TypeScript
implemented.
class ShopConfig {
public apiKey: string;
public products: any;
constructor(apiKey: string = 'trial') {
this.apiKey = apiKey;
//Fetch list of products from local Data-Base
this.products = expensiveDataBaseQuery();
}
protected copy(other: ShopConfig) {
for (const field in other) {
if (other.hasOwnProperty(field)) {
this[field] = other[field];
}
}
}
}
class ShopManager extends ShopConfig {
constructor(config: ShopConfig) {
super();
super.copy(config);
console.log('ShopManager configurations:', config);
}
}
No, type-script has no copy-constructor.
But I did workaround it, like:
ShopConfig
) to allow both constructor and copy-constructor types (using combination of |
operators in type).myParam instanceof ClassName
typeof myParam === 'primitiveName'
class ShopConfig {
public apiKey: string;
public products: any;
constructor( v: ShopConfig
| string | String
| null
= 'trial'
) {
if ( ! v) {
// ... Invalid parameters detected ...
throw new Error('ShopConfig: expected API-Key or existing instance');
} else if (v instanceof ShopConfig) {
// ... Copy-constructor detected ...
// Customize below to match your needs.
for (const field in v) {
if (v.hasOwnProperty(field)) {
this[field] = v[field];
}
}
} else if (typeof v === 'string' || v instanceof String) {
// ... Normal-constructor detected ...
this.apiKey = v.toString();
// Fetch list of products from local Data-Base
this.products = expensiveDataBaseQuery();
}
}
}
class ShopManager extends ShopConfig {
constructor(config: ShopConfig) {
super(config);
console.log('ShopManager configurations:', config);
}
}
Note that there is nothing complicated in the above copy-related-logic, which has very few lines, else we would create a _copy(...)
method (in base-class, maybe protected
instead of private
, to be overridable), and call that from same-class' constructor
(right after type-check).
Also, maybe
ShopConfig
should be last in constructor's type-chain, to prioritize normal-constructing over copy-constructing, but we place it first to ensure users notice that copying is possible.