0

Node is not happy about something in the Javascript that TypeScript is generating and I can't figure out why. Here is the code

Person.ts:

export module Models {
    export class Person {
        id: number;
        firstName: string;
        lastName: string;

        constructor(f: string, l: string) {
            this.firstName = f;
            this.lastName = l;
        }

        public saySomething(): void {
            console.log("my name is %s %s", this.firstName, this.lastName);
        }
    }
}

Database.ts:

import P = module("Person");

export module Database {
    export class DB {
        public findPerson(id: number): P.Models.Person {
            return new P.Models.Person("a", "b");
        }
    }
}

Test.ts:

var D = require("./DB");
var db = new D.Database.DB();
var p = db.findPerson(123);
p.saySomething();

It compiles fine down in Javascript, but there appears to be something wrong with the DB.js file that is being created. When I try to run Test.js in node I get this:

$node Test.js
DB.js:2
(function (Database) {
^
TypeError: object is not a function
    at Object.<anonymous> (DB.js:2:1)
    at Module._compile (module.js:449:26)
    at Object.Module._extensions..js (module.js:467:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.require (module.js:362:17)
    at require (module.js:378:17)
    at Object.<anonymous> (Test.js:1:73)
    at Module._compile (module.js:449:26)
    at Object.Module._extensions..js (module.js:467:10)

It's happening during the import of DB.js. Oddly enough, if I change the findPerson() method to return a string instead of a Person it works fine. It has something to do with creating that Person object.

Here is the Javascript:

(function (Models) {
    var Person = (function () {
        function Person(f, l) {
            this.firstName = f;
            this.lastName = l;
        }
        Person.prototype.saySomething = function () {
            console.log("my name is %s %s", this.firstName, this.lastName);
        };
        return Person;
    })();
    Models.Person = Person;    
})(exports.Models || (exports.Models = {}));


var P = require("./Person")
(function (Database) {
    var DB = (function () {
        function DB() { }
        DB.prototype.findPerson = function (id) {
            return new P.Models.Person("a", "b");
        };
        return DB;
    })();
    Database.DB = DB;    
})(exports.Database || (exports.Database = {}));


var dbx = require("./DB")
var db1 = new dbx.Database.DB();
var p = db1.findPerson(123);
p.saySomething();

3 Answers 3

5

without semicolon after var P = require("./Person") javascript thinks than next (...) is call of a function. but you seem have it in Database.ts, so Typescript probably loosing some semicolons in compilation.

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

3 Comments

Wow, you're absolutely right. The missing semi-colon in the DB.js file is what is causing the issue. I guess I should file a bug with Microsoft.
Looks like someone already did; just vote it up: typescript.codeplex.com/workitem/364
Or maybe that was you, haha...just noticed this answer was from November.
0

The main issue is that you are importing a module named Person, where I think you mean to import the Models module that contains a class named Person.

When you are targeting nodejs, or other CommonJS platforms, you omit the module declarations.

You can also take advantage of auto-properties in the constructor.

So you would have Models.ts:

export class Person {
    id: number;

    constructor (public firstName: string, public lastName: string) {

    }

    public saySomething(): void {
        console.log("my name is %s %s", this.firstName, this.lastName);
    }
}

And Database.ts

import models = module("Models");

export class DB {
    public findPerson(id: number): models.Person {
        return new models.Person("a", "b");
    }
}

2 Comments

Maybe I'm not understanding the concept behind modules correctly, but what I was attempting to do was group related classes together using the module keyword. So I would have the Person, Car, Dog classes under the "Models" module and have Query, Table, Recordset under the "Database" module. Basically using the "module" keyword like a C# namespace. I could do what you're saying, but then I have to put all my model classes in one giant file, which I don't want to do.
You can still do something similar in CommonJS - you can use a nested folder structure to have a "./Models/Person" module, a "./Models/Animal" module and so on. The Person.ts and Animal.ts are inherent modules, but you can export your classes from them and they are grouped into the Models namespace.
0

For me the problem is that I was trying to import a function for file B, in my main file A

File B:

//other stuff

export function doSomething() {
  //....
}

File A:

import {doSomething} from "./fileB";

doSomething()

BUT, above the function doSomething() in fileB, there was an explicit export like this: File B:


function doSomethingElse() {
    // legacy stuff
}

module.exports = doSomethingElse;

export function doSomething() {
  //....
}

Somehow, PHP Storm didn't signal me...

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.