2

Hi!

First off, sorry if this has been asked before, I tried some Googling but wasn't able to find anything (at least nothing that I recognised as being the same problem). I'm new to Typescript so still getting to grips!

I'm making a little game as a project to brush up on my JavaScript, and decided to use Typescript since it seems like a good fit for modularising my application. It's all running on a node server - I can provide version numbers if required!

I have two files, player.ts and scene.ts, these both belong to the same module (in that they are part of my program, but I want to split them up for the sake of modularity):

player.ts

module TheGame {
    export class Player {
        name: string;
        constructor(name: string) { 
            this.name = name;
        }
    }
}

scene.ts

///<reference path="player.ts"/>
///<reference path="../typings/threejs/three.d.ts"/>
import jquery = require("three");

module TheGame {
    export class Scene {
        player: any;
        constructor() {
            this.player = new Player('test');
        }
        //Use of Three throughout file
    }
}

Both of these files are in the same folder, and when I try to compile them with:

tsc player.ts scene.ts --module commonjs

I get the error:

testscene.ts(10,22): error TS2095: Could not find symbol 'Player'.

If I remove the reference and the import to Three, this compiles fine, but obviously I need to use Three in the class. (Three is also required in the player class, and probably more later) It seems like it actually compiles the JS files even though there's an error, I'm not sure why.

  • What am I not understanding about how this works?

  • Is there some restriction on using external modules and internal modules?

  • Is there a way to import all the external classes my application needs (Three, socket.io, etc.) in it's own TS file to make this work, if that's a solution?

Thanks in advance!

ANSWERED:

The solution was that, using commonJS, you need to explicitly export and import, and using modules doesn't really make sense (thanks to @ssube and @BGR for the solution).

Working code:

player.ts

export class Player {
    name: string;
    constructor(name: string) { 
        this.name = name;
    }
}

export = Player;

scene.ts

///<reference path="../typings/threejs/three.d.ts"/>
import jquery = require("three");
import Player = require("./player");

class Scene {
    player: Player;
    constructor() {
        this.player = new Player('test');
    }
    //Use of Three throughout file
}

export = Scene;

2 Answers 2

3

If you want to use commonjs (and I think you should) you need to explicitly export and import try

player.ts

class Player {
    name: string;
    constructor(name: string) { 
        this.name = name;
    }
}

export = Player

scene.ts

///<reference path="../typings/threejs/three.d.ts"/>
import jquery = require("three");  //I guess 'jquery' is a typo
import Player = require('./Player')

class Scene {
    player: any; //any -> Player ?
    constructor() {
        this.player = new Player('test');
    }
    //Use of Three throughout file
}

export = Scene //if this makes sense
  • use of wrapper modules (like TheGame) do not really make sense when using commonJS (things are isolated)

  • you do not need to reference .ts files

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

3 Comments

Fantastic! This worked, however I had to change require('./Player') to require('./player') - I'm guessing this is just referencing the name of the .ts file (without the .ts)?
yes: it is the name of the .ts file without the ts extension
Also just as a note, player: Player; is what it should be, i think i left the any in from debugging
1

Since you've defined them as modules, Player wouldn't be visible to TheGame even if they were in the same file. That's the purpose and power of modules.

You need to import Player from player.ts within scene.ts to make it visible in that scope. Depending on your output, this may translate into an AMD or CommonJS require.

Referencing the file makes the compile aware of the definition and allows validation, but doesn't actually pull those symbols into the current scope and make them usable.

I would suggest making Player the default export from its file to simplify your imports into:

///<reference path="player.ts"/>
///<reference path="../typings/threejs/three.d.ts"/>
import jquery = require("three");
import Player = require("player");

1 Comment

So am I right in saying that even though they're in the same module name, they won't see each other because they're in physically different module blocks? I guess as @BGR mentioned in the other answer, it doesn't make sense to use the modules in commonJS anyway

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.