TypeScript class function not available

12

I'm trying to call a instance method of a TypeScript class (in an ASP.NET MVC project). However, at Runtime I get exceptions like 0x800a01b6 - JavaScript runtime error: Object doesn't support property or method 'checkString'.

I copied the generated JavaScript in a jsfiddle where the method seems to work.
I'm not really a JavaScript guy, so any help is much appreciated!

Things I have tried so far:

  1. different browsers (Chrome: Uncaught TypeError: undefined is not a function, FF: TypeError: this.checkString is not a function)
  2. clearing browser caches
  3. deleting the temporary files of IIS Express
  4. cleaning and rebuilding the solution
  5. not using the private modifier
  6. starting the project on another machine
  7. replacing the underscore.js call with a dummy to verfiy that's not the problem
  8. checked that the instance members are correctly set

This is the TypeScript code:

class FormData {
    BlogName: string;
    CacheTimeOut: number;
    CopyrightHolder: string;
    NavBarTitle: string;
    MarkdownExtra: boolean;
    MarkdownSanitize: boolean;
    RatingActive: boolean;
    HtmlEditor: boolean;

    constructor(blogName: string, cacheTimeOut: number, copyrightHolder: string, navBarTitle: string, markdownExtra: boolean, markdownSanitize: boolean, ratingActive: boolean, htmlEditor: boolean) {
        this.BlogName = blogName;
        this.CacheTimeOut = cacheTimeOut;
        this.CopyrightHolder = copyrightHolder;
        this.NavBarTitle = navBarTitle;
        this.MarkdownExtra = markdownExtra;
        this.MarkdownSanitize = markdownSanitize;
        this.RatingActive = ratingActive;
        this.HtmlEditor = htmlEditor;
    }

    private checkString(value: string): boolean {
        return _.isString(value) && value !== '';
    }

    validate(): boolean {
        return (this.checkString(this.BlogName) && this.checkString(this.CopyrightHolder) && this.checkString(this.NavBarTitle) && _.isNumber(this.CacheTimeOut) && !_.isNull(this.MarkdownExtra) && !_.isNull(this.MarkdownSanitize) && !_.isNull(this.RatingActive));
    }       
}

//I'm calling the validate function like that (from within the same module)
var form = getFormData(); //returns a FormData instance
if (!form.validate()) {
    //foo
}

And here the generated JavaScript:

var FormData = (function () {
    function FormData(blogName, cacheTimeOut, copyrightHolder, navBarTitle, markdownExtra, markdownSanitize, ratingActive, htmlEditor) {
        this.BlogName = blogName;
        this.CacheTimeOut = cacheTimeOut;
        this.CopyrightHolder = copyrightHolder;
        this.NavBarTitle = navBarTitle;
        this.MarkdownExtra = markdownExtra;
        this.MarkdownSanitize = markdownSanitize;
        this.RatingActive = ratingActive;
        this.HtmlEditor = htmlEditor;
    }
    FormData.prototype.checkString = function (value) {
        return _.isString(value) && value !== '';
    };

    FormData.prototype.validate = function () {
        return (this.checkString(this.BlogName) && this.checkString(this.CopyrightHolder) && this.checkString(this.NavBarTitle) && _.isNumber(this.CacheTimeOut) && !_.isNull(this.MarkdownExtra) && !_.isNull(this.MarkdownSanitize) && !_.isNull(this.RatingActive));
    };
    return FormData;
})();
javascript
typescript
asked on Stack Overflow Apr 14, 2014 by marce • edited Apr 14, 2014 by marce

2 Answers

27

This is probably because of the wrong this at runtime. You can use a lambda function ()=>{} instead of function to make sure that the this is lexically scoped in the generated JavaScript:

validate = (): boolean => {
        return (this.checkString(this.BlogName) && this.checkString(this.CopyrightHolder) && this.checkString(this.NavBarTitle) && _.isNumber(this.CacheTimeOut) && !_.isNull(this.MarkdownExtra) && !_.isNull(this.MarkdownSanitize) && !_.isNull(this.RatingActive));
    } 

Please search for what this means in javascript and typescript to learn more.

answered on Stack Overflow Apr 14, 2014 by basarat • edited Apr 14, 2014 by basarat
6

Another Bypass-Style Solution:
instead of using this., you can use super..

  • A prerequisite is to create two classes, one as a Base Class, another as a Usable Class.
  • The Base Class contains the methods that you want to call in the constructor.
  • The Usable Class calls the Method from within it's constructor using super.myMethod(); instead of this.myMethod();

This is a subtle benefit made easily possible thanks to Typescript. :)

Example:
Source: Typescript Bypass Solution on Stackoverflow

export class myBaseClass
{
    constructor(ctx:any)
    {
        this.ctx = ctx;         // Audio context saved into member variable of class
    }
    myBaseMethod()
    {
        // Do Complex Work
    }
}

export class myUsableClass extends myBaseClass
{
    constructor(ctx:any)
    {
        super(ctx);
        super.myBaseMethod(); // Use super., Not this.
    }

}
answered on Stack Overflow May 21, 2014 by JThora • edited May 23, 2017 by Community

User contributions licensed under CC BY-SA 3.0