Mehran
Mehran

Reputation: 16911

Tackle RequireJs circular dependency in TypeScript

I'm using TypeScript + AMD (RequireJs) and I'm facing a problem regarding circular dependency. tsc deals with circular dependency pretty smooth but when it's run time, it took me hours to figure out that I'm facing a circular dependency problem.

Here's my scenario:

Singleton.ts

import Window = require("./Window");

class Singleton
{
    private w : Window;
    private counter : number = 0;

    constructor() {
        w = new Window();
    }

    Increment() : number {
        return ++this.counter;
    }
}
export = Singleton;

Window.ts

import Singleton = require("./Singleton");
declare var global_instance : Singleton;

class Window
{
    private my_number : number = 0;

    constructor() {
        this.my_number = global_instance.Increment();
    }
}
export = Window;

As simple as it seems, it leads to a circular dependency and thus I'm unable to implement it in a browser. But as I said tsc deals with it perfectly without any problem. As I searched the Internet I found a couple of proposed solutions:

This one suggests adding a typeof before the type to prevent compiler from actually putting the type's file in require list. But it results in a dozen of compiler errors so it's out.

This one sounds promising but it's a RequireJs solution and I'm not sure how to implement it in TypeScript!

Does anyone have any solution how to deal with circular dependency while benefiting from type checking of tsc compiler?

Upvotes: 1

Views: 672

Answers (2)

Adam
Adam

Reputation: 131

if you are using the requirejs.d.ts

amend it with this

declare var exports: any;

and then your class you explicitly call exports.

import Window = require("./Window");

class Singleton
{
    private w : Window.Window;
    private counter : number = 0;

    constructor() {
        w = new Window.Window();
    }

    Increment() : number {
        return ++this.counter;
    }
}
exports.Singleton = Singleton;
export = Singleton;

Window.ts

import Singleton = require("./Singleton");
declare var global_instance : Singleton.Singleton;

class Window
{
    private my_number : number = 0;

    constructor() {
        this.my_number = global_instance.Increment();
    }
}
exports.Window = Window;
export = Window;

I wish there was a way, such as in node to just set exports directly but that does not seem to work, at least for me.

Upvotes: 0

Fenton
Fenton

Reputation: 251242

Because these files are absolutely tied together, put them in a single file. Not only does it solve your circular reference, but it also means one less HTTP request (which you are guaranteed to need).

Once they are in the same file, you may decide to merge the concepts further, or split out that part that they both depend on to remove the circular dependency.

Upvotes: 2

Related Questions