Reputation: 414
Im trying to rewrite JavaScript code to TypeScript, but I'm running into some problems when trying to import a class into a different TypeScript file.
This used to be done with jQuery Namespaces, where it worked fine.
My situation is:
file Layouts:
import { Commands } from './funnel.commands'
var commands = new Commands(); /*<--- problematic line*/
export class Layouts {
loadHtmlSubLayout(done: Function, layoutname: string): void {
/*...*/
commands.CloseSubLayout();
/*...*/
};
closeSubLayout(layoutContent): void {
/*...*/
};
}
file Commands:
import { Layouts } from './funnel.layouts'
var layouts = new Layouts();
export class Commands {
GotoLayout(el, cmd: CommandObj): void {
/*...*/
layouts.loadSpecificLayout(layouts.onLayoutSwitched, layoutName);
};
CloseSubLayout(): void {
/*...*/
if ($subLayoutContent.length !== 0) {
layouts.closeSubLayout($subLayoutContent);
}
};
}
Whenever I try to run this, I get the error 'Commands is not a constructor'. How can I make sure this works without having to move the methods around?
Upvotes: 1
Views: 2049
Reputation: 19947
One of these 2 module has to back-off and use async/lazy init the other in order to break the circular import chain.
In your example, I assume Commands
is used ahead of Layouts
. So you can do the following:
file funnel.commands
import { Layouts } from './funnel.layouts'
var layouts = new Layouts
export class Commands {
CloseSubLayout(): void {
layouts.closeSubLayout({});
};
}
file funnel.layouts
import { Commands } from './funnel.commands'
var commands: Commands
setTimeout(() => {
commands = new Commands()
})
export class Layouts {
loadHtmlSubLayout(): void {
commands.CloseSubLayout();
};
closeSubLayout(layoutContent): void {
console.log('You just called Layouts.closeSubLayout()')
};
}
other party:
import { Commands } from './funnel.commands'
var commands = new Commands()
commands.CloseSubLayout()
Above solution should work, but circular dependency is still an anti-pattern. Since you're rewriting a codebase, better refactor that part. I suggest use some sort of dependency injection pattern.
file dependencies
export const dependencies: any = {
_register(map: any) {
Object.assign(this, map)
}
}
file funnel.commands
import { dependencies as dep } from './dependencies'
export class Commands {
CloseSubLayout(): void {
dep.layouts.closeSubLayout({});
};
}
file index
import { Commands } from './funnel.commands'
import { Layouts } from './funnel.layouts'
import { dependencies } from './dependencies'
var commands = new Commands()
var layouts = new Layouts()
dependencies._register({ commands, layouts })
Upvotes: 2