Search code examples
typescriptamdwebpack

How do you use typescript internal modules with AMD modules


I'm not sure if I'm structuring my typescript incorrectly so may be asking the wrong question here.

I've got 2 related classes 1 interfaces in separate files in the same folder.

I've wrapped them in a module because that feels like what I should do coming from C#.

This is all angularjs so it does it's own DI which might be important but probably isn't.

File 1:

export module Module1{
    export interface IService{
    }
}

File2:

export module Module1{
    export class Implementation implements IInterface{
    ...
    }
}

File 3 is angular code that uses the angular injected instance of IInterface. If I import File2 using require("./File2") it works but I'd rather import the whole of Module1, something like below, so I don't have to require each class individually (as this is obviously a simplified case).

import authModule = require('Module1');

var assetStreamApp = angular.module("[])
    .run(['IInterface'], (instance: IInterface) => {
        instance.doSomething();
    });

Is this possible?

I don't want to have to import every file individually and then choose a different alias for each "module" to namespace the types when it feels like I should be able to do that once.

Edit: After a little more reading I think I've worked out some of the terminology. I want to use typescript internal modules in a project but also use AMD modules as split points so I can use webpack's code splitting.


Solution

  • Ideally you should just use external modules and not mix internal with external modules.

    This has been discussed in detail here and here.

    I would recommend doing... IService.ts:

    interface IService {
    }
    
    export = IService;
    

    Implementation.ts:

    import IInterface = require("./IInterface");
    
    class Implementation implements IInterface{
    ...
    }
    
    export = Implementation;
    

    And then import them appropriately into your file:

    import IService = require("./IService");
    import Implementation = require("./Implementation");
    
    // use IService and Implementation here
    

    Combining Multiple Modules into One Module

    That being said, if you really wanted to, you could use IService.ts and Implementation.ts above and then create a file called Module1.ts where you import then export your modules like so:

    export import IService = require("./IService");
    export import Implementation = require("./Implementation");
    

    Then in your code you can use it like such:

    import Module1 = require("./Module1");
    
    // use Module1.IService or Module1.Implementation here
    

    Combining Multiple Modules with ES6 Modules

    By the way, I wanted to point out that doing this is very convenient if you use ES6 modules...

    IService.ts:

    interface IService {
    }
    
    export default IService;
    

    Implementation.ts:

    import IInterface from "./IInterface";
    
    export default class Implementation implements IInterface {
    ...
    }
    

    Module1.ts:

    // re-export the modules
    export {default as IService} from "./IService";
    export {default as Implementation} from "./Implementation";
    

    Then when you use this module you can easily access what you want out of it. Here are some example import statements:

    // import only IService
    import {IService} from "./Module1";
    // import IService and Implementation
    import {IService, Implementation} from "./Module1";
    // or implement everything on a Module1 object
    import * as Module1 from "./Module1";