Query
Greetings, encountering an issue with the code snippet below:
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)
I am currently delving into the root cause of this error and exploring how to effectively implement the factory pattern in typescript/javascript. There are certain behaviors that appear perplexing:
- If I exclude the second-child segment from the code, everything runs smoothly except when swapping the order of export statements in the index.ts file between child and parent.
- Merging the files child.ts and second-child.ts into a single file containing both classes eliminates the exception.
- Is the error related to circular dependencies? If so, what exactly triggers issues with circular dependencies in typescript/javascript?
- Could someone provide insight into the behavior observed in the code example?
To avoid the error, one could deviate from utilizing the type "this" while employing the factory Method for implementing the parent class, although it offers convenience. The objective behind the abstracted method duplicate is to yield a subclass instance, a repetitive implementation in every subclass may result in higher complexity within my real-world project.
Structure of Project:
src/
child.ts
factory.ts
index.ts
parent.ts
main.ts
second-child.ts
Content Overview
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 Insight
- Starting point: main.ts
- index.ts orchestrates content exports from child.ts, factory.ts, parent.ts, second-child.ts
Sample Playground