Klaus Nji
Klaus Nji

Reputation: 18857

TypeScript internal module usage

I have a class named BMW defined in BMW.ts as follows:

///<reference path="../Thing.ts"/>

module Entities.Cars {

    import e = Entities;

    export class BMW extends Vehicle {

        public series: string;

         constructor ( model : string, series : string) {
            super("BMW", model)
            this.series = series;
        }

         drive() {
             alert("driving a bimmer is a different kind of feeling");
         }       

         toString() : string
         { 
             return this.getName() + " " + this.series + " " + this.getType();
         }
    }
}

In another file Thing.ts, I have Vehicle and Thing classes defined as follows:

module Entities {

    // Class
    export class Thing {

        private _name: string;
        private _type: string;

        // Constructor
        constructor (public name: string, public type: string) {
            this._name = name;
            this._type = type;
         }

        getName(): string { return this._name; }
        setName(name: string) { this._name = name; }


        getType(): string { return this._type; }
        setType(name: string) {
            this._type = name;
        }

        toString() : string
        { 
            return "Entities.Thing";        
        }
    }

    export class Vehicle extends Thing {

        public cargoCapacity: number;
        public fuelType: string;
        public owner: string;

        constructor (make: string, model : string) {
            super(make, model)
        }

        drive() {
        }

        toString(): string {
            return "Entities.Vehicle";
        }
    }
}

When I attempt to execute the following code after referencing Thing and BMW TypeScript files:

var car = new Entities.Cars.BMW("335i", "E90");
car.drive();

I get an exception with the following error " Microsoft JScript runtime error: Unable to get value of the property 'BMW': object is null or undefined". The generated Javascript for BMW has an error. What is wrong with my above snippet?

Upvotes: 2

Views: 2396

Answers (2)

Valentin
Valentin

Reputation: 8084

There is nothing wrong with your code so it seems like your import order for the generated javascript files is wrong. The specification says the following:

Initialization order of the source files that make up the global module ultimately depends on the order in which the generated JavaScript files are loaded at run-time (which, for example, may be controlled by tags that reference the generated JavaScript files).

I have generated a file app.ts as follows:

///<reference path='Things.ts'/>
///<reference path='bmw/BMW.ts'/>
var car = new Entities.Cars.BMW("335i", "E90");
car.drive();

At this point you have two options:

  1. Let the compiler determine the correct order for executing the files by generating a single output file

    tsc --out app.js app.ts

    Then you only have to source app.js.

  2. Specify the correct order manually. For me, the following is the only order that works without throwing errors.

    <html>
        <head>
            <script src="Things.js"></script>
            <script src="bmw/BMW.js"></script>
            <script src="app.js"></script>
        </head>
        <body>
        </body>
    </html>
    

Upvotes: 6

Arek Bal
Arek Bal

Reputation: 21

Your code is fine.

My guess is that you are not placing script tags in your head element properly(wrong order, or ommitting some).

The simplest way to solve this, and to not have to remember about proper declaration sequence is to use single .js output file from tsc compiler by setting --out option.

EDIT: Depending on which js scenario you are working on(WSH, web app or some other js environment), you need to link js source files differently. With wsh for instance, you could use FileSystemObject to read a source file, then evaluate it. Or you could use AMDs...

Upvotes: 0

Related Questions