0

I have been using TypeScript at work where we use RequireJS as our AMD loader, and it's working quite well. I'd like to convert some of my personal JS libraries to TypeScript and am wondering - Is it possible using TypeScript's built in module system to export a global AND define using require/amd if the end user happens to be using it?

I'd like to avoid breaking compatibility with my existing users / forcing them into Require.

My Existing JS file is laid out as such that it defines a global AND if define is defined, defines TickerGraph:

var TickerGraph = (function () { …class code… });

if( typeof define == "function" ) {
    define([], function() {
        return TickerGraph;
    });
}

In my TypeScript rewrite, I've laid it out with the module type defined as UMD as follows:

export = class TickerGraph { …class code… }

That outputs

(function (dependencies, factory) {
    if (typeof module === 'object' && typeof module.exports === 'object') {
        var v = factory(require, exports); if (v !== undefined) module.exports = v;
    }
    else if (typeof define === 'function' && define.amd) {
        define(dependencies, factory);
    }
})(["require", "exports"], function (require, exports) {
    "use strict";
    return (function () {

Which checks for define / exports but does NOT define a global…

I've experimented and eliminating the export all together exports the global, but of course no longer defines. Any help here would be greatly appreciated.

1 Answer 1

1

The only way to do that is to not use typescript module system, it appears.

Typescript compiler itself is a good example - lib/tsc.js can be used as both a node module and a global script.

There is not-well-known (for me, at least) set of rules they have to follow to achieve that:

  • don't have any export or import at top level. Every export they have is inside namespace ts { }

  • one file can use a symbol from another file, provided that each file has all its content in namespace ts { }. You have to make sure that all interdependent files are compiled together, or have proper /// <reference directives. This assumes that you use --outFile option to produce single output file from several typescript files.

In essence, you are creating one giant global script composed from all the files, with everything inside namespace ts. Resulting output will have var ts at the top level which will become global if you include it as a plain script.

In order to make it available as node module, they have this code in shims.ts:

// Here we expose the TypeScript services as an external module
// so that it may be consumed easily like a node module.
declare var module: any;
if (typeof module !== "undefined" && module.exports) {
    module.exports = ts;
}

You will have to do something similar for your module, using define instead of module. There is no built-in support for that, as far as I know.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.