Typescript Inheriting Through CommonJS Modules - Circular Dependencies

I cannot get inheritance to work with CommonJS modules generated with typescript 1.0 ( tsc is done with --module commonjs )

This fails if two classes that inherit the same base class call each other "through" the base class.

It seems that the first class imports the base class, which imports the second class, which also imports the base class, but the last import of the base class does not work.

The following is an example illustrating this behavior.

Is there anything in the typescript or CommonJS specs that prevent me from doing this, or is this a bug?

=== Example ===

This exciting piece of software does not work by running Lower.test.ts . What he is just trying to achieve is to load a word in Lower , which stores it in lower case, and then using the inherited toUpper() method from the Base class, converts it to upper case using the Upper class (which also inherits Base )

Lower.test.ts

 import Lower = require('./Lower') console.log(new Lower('smallcaps').toUpper()) 

Base.ts

 import Upper = require('./Upper') class Base { word: string toUpper(): string { return new Upper(this.word).word } } export = Base 

Upper.ts

 import Base = require('./Base') class Upper extends Base { constructor(word:string) { super() this.word = word.toUpperCase() } } export = Upper 

Lower.ts

 import Base = require('./Base') class Lower extends Base { constructor(word:string) { super() this.word = word.toLowerCase() } } export = Lower 
+1
inheritance commonjs typescript
Jul 07 '14 at 17:55
source share
2 answers

After some research and testing, this ends with a circular dependency case.

The problem is quite well documented and various solutions are proposed:

  • Export to requiring : here
  • Delay require or via injection: here
  • Moving Claims Around: A Pretty Long List Here

Unfortunately, there is very little control over where import and export statements can be set in Typescript, which only shorten injection solutions. The rewritten Base class is shown below.

Circular dependencies are a pain in Javascript modular projects. Typescript somehow aggravates the situation. This is bad news for a language that should solve large projects.

EDIT I opened the case and submitted the proposed transpiler fix to the Typescript project: here

Base.ts

 //This import will "fail" by importing an empty object but is needed to trick the compiler //An alternative is to design and Upper.d.ts definition file and reference it import Upper = require('./Upper') class Base { //Upper is a sub-class of Base and needs to be injected to be instantiated private _Upper: typeof Upper word: string constructor(_Upper: typeof Upper) { this._Upper = _Upper } toUpper(): string { //This where the injection is used return new this._Upper(this.word).word } getUpperWord(upper: Upper): string { //The injection is not reauired in this case return upper.word } } export = Base 

Upper.ts

 import Base = require('./Base') class Upper extends Base { constructor(word:string) { super(Upper) this.word = word.toUpperCase(); } } export = Upper 
+2
Jul 09 '14 at 9:25
source share
— -

It is usually best to depend in one direction only - in accordance with SOLID principles.

However, since you always need both Base and Upper (i.e. you cannot use them without the other), you can add them to the same module ...

base.ts

 export class Base { word: string toUpper(): string { return new Upper(this.word).word } } export class Upper extends Base { constructor(word: string) { super() this.word = word.toUpperCase() } } 

lower.ts

 import b = require('base') class Lower extends b.Base { constructor(word: string) { super() this.word = word.toLowerCase() } } export = Lower 

app.ts

 import Lower = require('lower'); console.log(new Lower('smallcaps').toUpper()); 
0
Jul 07 '14 at 19:09
source share



All Articles