0

Following the tutorial on this page I have the following JavaScript:

function A(id) {
    var about = {
        Version: "0.0.0.1",
    };

    if (id) {
        if (window === this) {
            return new A(id);//<-Error in typescript
        }

        this.e = document.getElementById(id);
        return this;
    } else {
        return about;
    }
};

A.prototype = {
    doSomething: function () {
        //Some logic
        return this;
    }
}

JavaScript Usage:

var result = A("test");//The type of result should be 'A'
result = new A("test");//The type of result should be 'A'
result = A("test").doSomething();//The type of result should be 'A'
result = new A("test").doSomething();//The type of result should be 'A'

I want to create a library based on TypeScript that has the same usage. How can that be done?

If I try to just put this in a '.ts' file and compile I get an error saying: Error TS2350: Only a void function can be called with the 'new' keyword.

Also I am not sure how the usage with and without the 'new' keyword can be achieved as I am trying to make a library in typescript that can be used in javascript and not to make the user have to use the 'new' keyword.

P.S.
I know I can create a javascript file with a '.d.ts' file but that is not the purpose.

4
  • 1
    The one who down voted can at least explain why? Commented Apr 12, 2016 at 14:22
  • what exactly are you asking here? Commented Apr 12, 2016 at 14:27
  • 1
    still not clear. what's up with using new? what are you trying to achieve? also, what's doSomething? as it's not in the code at all. It will be best if you explain exactly what you want, because I'm not about to read that tutorial you linked to Commented Apr 12, 2016 at 14:45
  • @NitzanTomer Updated the question Commented Apr 12, 2016 at 15:11

2 Answers 2

2

TypeScript is trying to reconcile the multiple purposes of A() and doesn't have enough information to figure out what you want it to look like.

This works:

function A(id): void {
    if (window === this) {
        return new A(id);//<-Error in typescript
    }

    this.e = document.getElementById(id);
    return this;
};

let result = A("test");
result = new A("test").doSomething();

But adding the version return block is confusing the compiler because A is now acting like two totally different things.

If you want to force the compiler to ignore the complaint you can do this:

function A(id): void {
    var about = {
        Version: "0.0.0.1",
    };

    if (id) {
        if (window === this) {
            return new A(id);//<-Error in typescript
        }

        this.e = document.getElementById(id);
        return this;
    } else {
        return <any>about;
    }
};

let result = A("test");
result = new A("test").doSomething();

But I don't recommend it. What you are trying to do is part of what TypeScript is trying to protect against. I don't know of a way to make the typings on this one "just work".


Edit: In response to your comment, I recommend something more like this:

class A {
    public static about = {
        Version: "0.0.0.1"
    };

    private e: HTMLElement;

    constructor(id) {
        this.e = document.getElementById(id);
    }

    public doSomething() {
        //Some logic
        return this;
    }
}

let result = new A("test");
result.doSomething();

let about = A.about;
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks. I updated the question to reflect better what I want. Also, can I do this using class or something else that is more suitable for typescript?
I updated my answer with a more detailed example. If you really need both A(id) and new A(id) patterns it gets more tricky. I chose to only keep the new A(id) pattern.
I need both. I want the JS users not to get an exception just because they didn't do 'new'. How is that possible? Can you show an example?
@RandallFlagg class in es6 is always run in strict mode, so it will throw an error without new. From my opinionated perspective: If you're making a brand new library, plan it around es6. Your consumers will have to learn it anyway. Don't hack the language just to let your consumers write incorrect code.
@MrHen Thanks for your help. That is basically what I wanted.
0

This is the final code I came up with thanks to MrHen help:

class A {
    public element;
    public test;
    public doSomething;

    constructor(id) {
        if (id) {
            if (window === this as any) {
                return new A(id);//<-Error in typescript
            }

            this.element = document.getElementById(id);
            this.test = function () {
                console.log("testing"); return this;
            };
            this.doSomething = function () {
                console.log("doing something"); return this;
            };

            return this;
        }
    }
}

let result = ((A as any)("test") as A).doSomething();
result = new A("test").doSomething();

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.