25

Is there a convenient way to have global variables accessible within modules,without compiler errors, ie CANVAS_WIDTH used below?

    export class Bullet {


        x: number = 22;
        y: number = 22;

        constructor (speed: number) {
            this.xVelocity = speed;
        }

        inBounds() {
            return this.x >= 0 && this.x <= CANVAS_WIDTH &&
                this.y >= 0 && this.y <= CANVAS_HEIGHT;
        };
}
}
3
  • where you will set the value for CANVAS_WIDTH? Commented Dec 11, 2012 at 12:16
  • in the game class which imports the module with the Bullet class GameObjects = module("GameObjects") Commented Dec 11, 2012 at 12:23
  • 1
    You have CANVAS_WIDTH in Game class and need to access it in Bullet class. Am i right? Commented Dec 11, 2012 at 13:30

3 Answers 3

31

You need to define those properties as static, then you can access it easily like this,

export class Game {
    static canvas: JQuery;
    static CANVAS_WIDTH: number;
    static CANVAS_HEIGHT: number;
    bullet: Bullet;

    constructor(canvasElem: JQuery) {
        Game.canvas = canvasElem;
        Game.CANVAS_WIDTH = Game.canvas.width();
        Game.CANVAS_HEIGHT = Game.canvas.height();
    }
}

export class Bullet {
    x: number = 22;
    y: number = 22;

    public inBounds() {
        // accessing static properties
        return this.x >= 0 && this.x <= Game.CANVAS_WIDTH && this.y >= 0 && this.y <= Game.CANVAS_HEIGHT;
    }
}

This compiles to:

define(["require", "exports"], function(require, exports) {
    var Game = (function () {
        function Game(canvasElem) {
            Game.canvas = canvasElem;
            Game.CANVAS_WIDTH = Game.canvas.width();
            Game.CANVAS_HEIGHT = Game.canvas.height();
        }
        return Game;
    })();
    exports.Game = Game;

    var Bullet = (function () {
        function Bullet() {
            this.x = 22;
            this.y = 22;
        }
        Bullet.prototype.inBounds = function () {
            // accessing static properties
            return this.x >= 0 && this.x <= Game.CANVAS_WIDTH && this.y >= 0 && this.y <= Game.CANVAS_HEIGHT;
        };
        return Bullet;
    })();
    exports.Bullet = Bullet;
});
//# sourceMappingURL=dhdh.js.map
Sign up to request clarification or add additional context in comments.

1 Comment

added the compiled JS file
3

This is a contrived example, but rather than trying to push to global scope, you can use the module scope to enclose a variable that will be used from several classes.

module MyModule {
    var x: number = 5;

    export class FirstClass {
        doSomething() {
            x = 10;
        }
    }

    export class SecondClass {
        showSomething() {
            alert(x.toString());
        }
    }
}

var a = new MyModule.FirstClass();
a.doSomething();

var b = new MyModule.SecondClass();
b.showSomething();

All the usual rules about multiple things using the same variable apply here - you don't want to enforce a particular order of events on the calling code.


Compiles to:

var MyModule;
(function (MyModule) {
    var x = 5;

    var FirstClass = (function () {
        function FirstClass() {
        }
        FirstClass.prototype.doSomething = function () {
            x = 10;
        };
        return FirstClass;
    })();
    MyModule.FirstClass = FirstClass;

    var SecondClass = (function () {
        function SecondClass() {
        }
        SecondClass.prototype.showSomething = function () {
            alert(x.toString());
        };
        return SecondClass;
    })();
    MyModule.SecondClass = SecondClass;
})(MyModule || (MyModule = {}));

var a = new MyModule.FirstClass();
a.doSomething();

var b = new MyModule.SecondClass();
b.showSomething();

2 Comments

Does this still work in the latest version of typescript? It does not appear the example compiles...
added compiled js for comparison
1

I'm not sure I want to encourage this, but to answer the OP's question literally:

You can put anything you want into global scope and then refer to it elsewhere.

For instance, you could put the following on your index.html equivalent:

function logit(x, loc) {
  if (console && console.log) {
    console.log(loc, JSON.stringify(x, null, '  '));
  }
}

Now you can use this anywhere you want in one of at least two ways.

Kludge your global scope.

(window as any).logit(item, "some location")

Ewwww.

Use declare

You can also refer to it using declare.

So in a regular TypeScript file:

declare const logit: (x: any, loc: string) => void;
// you could also just use
// declare const logit: any;

export default class MyClass {
  public handleIt(x: string) {
    logit(x, "MyClass.handleIt");
    // ... logic
  }
}

Note that any file, not just "index.html", is fair game as a launching point to push stuff into the global scope. Just remember that you could get into trouble if you were, say, lazy loading a module.


Your example

So for you, set those two values globally however you want (or maybe a non-TypeScript library does it for you, which would almost make this a valid use case), and then do something like...

declare let CANVAS_WIDTH: number; // maybe const, I don't know your use case.
declare let CANVAS_HEIGHT: number;

export class Bullet {
  x: number = 22;
  y: number = 22;

  constructor (speed: number) {
    this.xVelocity = speed;
  }

  inBounds() {
    return this.x >= 0 && this.x <= CANVAS_WIDTH &&
    this.y >= 0 && this.y <= CANVAS_HEIGHT;
  };
}

But, again, this is highly anti-pattern, and probably indicates a code smell. You want to have static values on another class as Rajagopal 웃 suggests.

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.