Nikos
Nikos

Reputation: 7552

Typescript global variables

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;
        };
}
}

Upvotes: 25

Views: 61070

Answers (3)

ruffin
ruffin

Reputation: 17453

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.

Upvotes: 1

Fenton
Fenton

Reputation: 250842

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();

Upvotes: 3

Rajagopal 웃
Rajagopal 웃

Reputation: 8471

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

Upvotes: 31

Related Questions