Question
Hello, the following code example throws the error:
TypeError: Super constructor null of SecondChild is not a constructor
at new SecondChild (<anonymous>:8:19)
at <anonymous>:49:13
at dn (<anonymous>:16:5449)
Currently i am trying to understand what exactly the issue is about and how to implement the factory pattern in typescript/javascript. There are several behaviours which i don´t quite understand:
- If I remove the second-child of the code everything works fine except if I swap the order of the export statements in the index.ts file of the child and parent export.
- If I combine the files child.ts and second-child.ts into one single file which defines both classes the exception is also gone
- Is the error linked to the circular dependencies? And if so, what exactly is the problem behind circular dependencies in typescript/javascript?
- Can someone explain the behaviour of the code example to me?
It would be possible to prevent the error if i implemented the parent class without using the type "this" in combination with the factory Method but it seems pretty convenient. The goal behind the abstracted method duplicate is that it returns a subclass instance. I could implement it in every subclass but in my real world project the complexity is much higher.
Project structure:
src/
child.ts
factory.ts
index.ts
parent.ts
main.ts
second-child.ts
File Content
main.ts:
// Throws error
import { Child, Parent, SecondChild } from './index'
console.log(new Child().duplicate())
console.log(new SecondChild().duplicate())
console.log(new Parent().duplicate())
// Works as intended:
// import { Child, Parent} from './index'
// console.log(new Child().duplicate())
// console.log(new Parent().duplicate())
parent.ts
import { factory } from './factory'
export class Parent {
isChild = 0;
duplicate(): this {
return factory(this.isChild) as unknown as this;
}
}
child.ts
import {Parent} from './parent'
export class Child extends Parent{
override isChild = 1;
}
second-child.ts
import {Parent} from './parent'
export class SecondChild extends Parent{
override isChild = 2;
}
factory.ts
import { Child } from './child'
import { SecondChild } from './second-child'
import { Parent } from './parent'
export function factory(child: number):Child;
export function factory(...args: unknown[]):Parent {
switch (args[0]) {
case 1: {
return new Child()
}
case 2: {
return new SecondChild()
}
default: {
return new Parent();
}
}
}
index.ts
export * from './child'
export * from './second-child'
export * from './parent'
export * from './factory'
Project Description
- Entry point: main.ts
- index.ts exports the content of child.ts, factory.ts, parent.ts, second-child.ts