TypeScript: использование статических переменных с RequireJS AMD

Используя TypeScript 0.9.1.1, при попытке доступа к статической переменной из другого модуля/файла она не определена.

Пример кода:

App.ts:

import Game = require('Game');

var game = new Game();

Game.ts:

import Grid = require('Grid');

class Game
{
    public Grid: Grid;
    public static Game: Game;

    constructor()
    {
        Game.Game = this;
        this.Grid = new Grid();
        this.Grid.SeeIfStaticWorks();
    }
}

export = Game;

Grid.ts:

import Game = require('Game');

class Grid
{
    public SeeIfStaticWorks()
    {
        var shouldNotBeUndefined = Game.Game;
    }
}

export = Grid;

Проверка Game.Game перед вызовом this.Grid.SeeIfStaticWorks(); показывает, что он определен:

http://j.mp/1dCY8Ec

Но при попытке доступа к нему изнутри SeeIfStaticWorks() он не определен:

http://j.mp/1dCYISe

Вопрос: как получить доступ к статическим переменным из других модулей?


Обновление:

Запуск всего кода из одного файла позволяет использовать статическую переменную в модулях (demo здесь):

class Grid
{
    public SeeIfStaticWorks()
    {
        console.log(Game.Game);
        if (Game.Game)
            alert('Instance is defined!');
        else
            alert('Instance is undefined!');
    }
}

class Game
{
    public Grid: Grid;

    private static game : Game;
    public static get Game() : Game
    {
        if (this.game == null)
        {
            this.game = new Game();
        }

        return this.game;
    }

    constructor()
    {
        this.Grid = new Grid();
    }
}

var game = Game.Game;

game.Grid.SeeIfStaticWorks();

Если я использую ту же логику с AMD RequireJS, статическая переменная не определена при вызове SeeIfStaticWorks():

App.ts:

import Game = require('Game');

var game = Game.Game;

game.Grid.SeeIfStaticWorks();

Game.ts:

import Grid = require('Grid');

class Game
{
    public Grid: Grid;

    private static game : Game;
    public static get Game() : Game
    {
        if (this.game == null)
        {
            this.game = new Game();
        }

        return this.game;
    }

    constructor()
    {
        this.Grid = new Grid();
    }
}

export = Game;

Grid.ts:

import Game = require('Game');

class Grid
{
    public SeeIfStaticWorks()
    {
        console.log(Game.Game);
        if (Game.Game)
            alert('Instance is defined!');
        else
            alert('Instance is undefined!');
    }
}

export = Grid;

person Răzvan Flavius Panda    schedule 24.08.2013    source источник


Ответы (3)


Это связано с тем, что при анализе файла Game.ts Game.Game не устанавливается. Вы можете видеть это в сгенерированном javascript:

var Game = (function () {
    function Game() {
        Game.Game = this;
        this.Grid = new Grid();
        this.Grid.SeeIfStaticWorks();
    }
    return Game;
})();

Чтобы статические переменные были доступны при экспорте чего-либо, вы должны установить их в точке определения (не лениво, как в вашем случае). Так :

class Game
{
    public Grid: Grid;
    public static Game: Game = new Game(); // set it outside the constructor

    constructor()
    {
        this.Grid = new Grid();
        this.Grid.SeeIfStaticWorks();
    }
}

Вы можете увидеть сгенерированный javascript:

var Game = (function () {
    function Game() {
        this.Grid = new Grid();
        this.Grid.SeeIfStaticWorks();
    }
    Game.Game = new Game(); // Now this statement will execute when this javascript is parsed
    return Game;
})();

Как управлять синглтонами — это отдельный разговор. Но я считаю, что приведенного выше кода достаточно. (вы можете добавить дополнительные проверки, если вам нужен настоящий синглтон).

person basarat    schedule 24.08.2013
comment
Это также не сработает, потому что SeeIfStaticWorks() будет запущен до создания экземпляра Game.Game. Я опубликовал обновление вопроса с кодом, более близким к тому, что я мог бы использовать. Проблема выглядит так, как будто она может быть связана с RequireJS. Кстати, хорошие видео AngularJs / TS :) - person Răzvan Flavius Panda; 25.08.2013
comment
Поскольку это так не работает, не могли бы вы удалить ответ? Это поможет быстрее получить правильный ответ. - person Răzvan Flavius Panda; 31.08.2013

В случае, если это может кому-то помочь, мне удалось создать статические переменные с использованием AMD в рамках dojo, обернув его функцию «объявления» (собственная функция dojo для создания «классов»).

(function () {
'use strict';

define([
    'dojo/dom',
    'dojo/_base/lang',
    'dojo/_base/declare'
], function (dom, lang, declare) {


    var constants = {
        SOME_CONSTANT: 'Here is it!'
    };

    var Car = declare(null, {
        constructor: function() {

        },

        throttle: function() {
            console.log('Vrrr!');
        }
    });

    lang.mixin(Car, constants);
    return Car;

});

}());

в клиенте:

(function () {
'use strict';
define([
    'model/Car',
    'dojo/domReady!'
], function (Car) {
    var c = new Car();
    c.throttle();
    console.log(Car.SOME_CONSTANT);
});

}());

person JoaoPauloPaschoal    schedule 03.12.2014

Работает следующий независимый от порядка код. Демонстрационная игра перед сеткой:

class Game
{
    public Grid: Grid;
    public static Game;

    constructor()
    {
        Game.Game = this;
        this.Grid = new Grid();
        this.Grid.SeeIfStaticWorks();
    }
}
class Grid
{
    public SeeIfStaticWorks()
    {
        console.log(Game.Game);
        if (Game.Game)
            alert('Instance is defined!');
        else
            alert('Instance is undefined!');
    }
}
// Finally 
var daGame = new Game(); 

Или сетка перед игрой:

class Grid
{
    public SeeIfStaticWorks()
    {
        console.log(Game.Game);
        if (Game.Game)
            alert('Instance is defined!');
        else
            alert('Instance is undefined!');
    }
}
class Game
{
    public Grid: Grid;
    public static Game;

    constructor()
    {
        Game.Game = this;
        this.Grid = new Grid();
        this.Grid.SeeIfStaticWorks();
    }
}
// Finally 
var daGame = new Game(); 

Попробуйте онлайн.

person basarat    schedule 31.08.2013
comment
Извините, не хочу показаться грубым, но это не использование RequireJS и наличие модулей Game и Grid в разных файлах. Насколько я понимаю, проблема связана с циклическими ссылками в RequireJS, но решение не может быть применено, так как в TypeSCript требуется ключевое слово. - person Răzvan Flavius Panda; 01.09.2013