Scott
Scott

Reputation: 21501

How do I add a static method to my TypeScript class?

I am trying to define an API using TypeScript such that it can work like this:

// Create new user (Working)
var user : IUser = new Api.User({ firstName: "John", lastName: "Smith" });

// Delete existing user (Working)
Api.User.Delete(1);

// Load existing user (Unsure how to implement)
var user = Api.User(123);

My TypeScript:

module Api
{
    export class User
    {
        constructor(id : number)
        constructor(user : IUser)
        constructor(user? : any)
        {
            // ...          
        }

        static Delete(id : number) {}
    }
}

I am not sure how to have a static method Api.User() i.e. not use new. I don't know what to call this type of construct, which makes it difficult to research. :(

I did try adding an unnamed static to the User class, but this isn't right.

static (id : number)
{
    // ...
}

Upvotes: 2

Views: 2447

Answers (1)

WiredPrairie
WiredPrairie

Reputation: 59763

Option 1: export a function directly on the Api module

You can export a function on the Api module to retrieve/create a User instance:

module Api
{
    export class User
    {
    }

    export function GetUser(id: number):User {
        return new User();
    }
    // or a slightly different syntax (which generates different JavaScript):
    export var Delete = (id: number) => {

    };  
}

You can't have the class named User and the function also be User, so I've changed it to GetUser in the example.

You could then call:

Api.GetUser(1234)

or

Api.Delete(1234);

Option 2: Using an interface

You could also approach this by using an interface if you wanted to limit the ability of calling code from being able to instantiate instances of the inner class by using an interface instead. Below I've created a simple ISuperUser interface and and implementation of the class called SuperUserImpl. As the SuperUserImpl isn't exported, it's not publicly creatable. This is nice in that you could use simple Api.SuperUser(2345) to return new instances of a class that implements the ISuperUser interface.

module Api {    
    export interface ISuperUser {       
        id: Number;
        name: String;
    }   
    class SuperUserImpl implements ISuperUser
    {
        constructor(public id: Number) {                        
        }               
        public name: String;
    }   

    export var SuperUser = (id:Number):ISuperUser => {
        return new SuperUserImpl(id);       
    }   
}

var su : Api.ISuperUser = Api.SuperUser(5432);
alert(su.id);

Option 3: JavaScript and instanceof

There's a trick that is often used in JavaScript class constructor wherein the function/constructor for a new object checks to see whether it is of the right type (was the function called or created), and if not created, returns a new instance:

if (!(this instanceof User)) {
    return new User(id);
}

While correct, TypeScript when trying to call a constructor with that will cause a compiler warning. This will work, but with the compiler warning:

constructor(id: Number) {
    if (!(this instanceof User)) {
       return new User(id);
    }
}           

And later calling:

var u: Api.User = Api.User(543);

A compiler warning suggests, "did you forget to use 'new'?" It does produce valid JavaScript, just with a warning. I'd probably go with the static-like method approach to avoid the TypeScript compiler warning.

Upvotes: 2

Related Questions