Require.js singleton to TypeScript

Topics: General
Oct 19, 2012 at 7:56 PM
Edited Oct 19, 2012 at 7:57 PM

Here are two watered down example files. This is currently how they work as requirejs modules. I've shimmed api.js in my require config to define the export as API. The goal is that these will stay as singletons. I'm trying to convert them to TypeScript equivalents but can't quite figure out how to keep them as a singleton and pass them around to various modules like I do now.

RequireJS style

api.js

(function (global) {

    var API = global.API = {};
    API.version = '0.0.1';
    API.env = 'local';
    API.header = '';

} (this));

auth.js

define([
    'api',
], function (api) {
        'use strict';
        
        CommonAuth = {

            maxExpiredAuthorizationRetries: 1,
            
            getAuthorizationHeader: function () {
                return api.header;
            },
            
            setAuthorizationHeader: function (val) {
                api.header = val;
            }
            
        };

        return CommonAuth;

    }
);

TypeScript/AMD(requirejs) style

 I've got the following so far but this is obviously not what I am after.

auth.ts

// don't know how to fake this without creating a valid api module. requirejs shim is what handles my export
import api = module("api");

export module Common {

    class Auth {
          
        public maxExpiredAuthorizationRetries: number;

        constructor (maxExpiredAuthorizationRetries: number) {
            this.maxExpiredAuthorizationRetries = maxExpiredAuthorizationRetries;
        }

        public getAuthorizationHeader(): string {
            return api.header();
        }

        public setAuthorizationHeader(val: string): void {
            api.header(val);
        }
    }

    var auth = new Auth(1);
}

which compiles to auth.js (tsc auth.ts --module amd`)

define(["require", "exports", "api"], function(require, exports, __api__) {
    var api = __api__;

    (function (Common) {
        var Auth = (function () {
            function Auth(maxExpiredAuthorizationRetries) {
                this.maxExpiredAuthorizationRetries = maxExpiredAuthorizationRetries;
            }
            Auth.prototype.getAuthorizationHeader = function () {
                return api.header();
            };
            Auth.prototype.setAuthorizationHeader = function (val) {
                api.header(val);
            };
            return Auth;
        })();        
        var auth = new Auth(1);
    })(exports.Common || (exports.Common = {}));

})
Oct 21, 2012 at 6:09 AM

Hey ryan,  

In my testing with TypeScript, I have found that Singleton instances need to be CommonJS, not AMD.

Looking at the generated code, the require statement is looking for __api__ have you tested exporting api.js as __api__ in your shim, and not API ?  

Oct 22, 2012 at 2:04 PM

Hey rozentalsn. My modules must be AMD. As far as __api__ that isn't a problem because that's just the alias for the module which is correctly included in the define as just plain "api". I believe that marking all of my class members as static is a working solution for me as far as singletons go.

Thanks for the suggestions.

Coordinator
Oct 22, 2012 at 5:28 PM

I may not fully understand the detail of the original code you are finding difficult to model - but if you are trying to recreate what you originally had in auth.js, is this what you are looking for?

import api = module("api");
export var maxExpiredAuthorizationRetries = 1;
export function getAuthorizationHeader() {
    return api.header;
}
export function setAuthorizationHeader(val) {
    api.header = val;
}

 

 

Oct 22, 2012 at 6:08 PM

lukeh, that does help. Without it I had to do this

export class Auth {
    public static maxExpiredAuthorizationRetries: number = 1;
}

// consume it
import Auth = module('auth');
Auth.Auth.maxExpiredAuthorizationRetries

In CommonJS I believe I could do something like this to avoid the naming oddity. I don't think I can do that with TypeScript yet though aside from creating a variable to rename Auth.Auth.

import Auth = module('common.auth').Auth;