Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Default value of Type in Generic classes in Typescript

I need to set a default value of a variable based on its type in Typescript generic classes like below

  class MyClass<T>{
      myvariable: T // Here I want to set the value of this variable 
                    // with the default value of the type passed in 'T'
    }

For example if the T is number then the default value of the variable myvariable should be "0", similarly for string it should be empty string and so on..

like image 684
Rishi Tiwari Avatar asked Jul 04 '16 05:07

Rishi Tiwari


1 Answers

You can't do that as the actual type which is T will only be known at runtime.

What you can do:

abstract class MyClass<T> {
    myvariable: T;

    constructor() {
        this.myvariable = this.getInitialValue();
    }

    protected abstract getInitialValue(): T;
}

Now you just extend this class, like so:

class MyStringClass extends MyClass<string> {
    protected getInitialValue(): string {
        return "init-value";
    }
}

Edit

What you're asking for can not be done because T only exists in the typescript realm, and it doesn't "survive" the compilation process.

For example, this:

class MyClass<T> {
    myvariable: T;

    constructor(value: T) {
        this.myvariable = value;
    }
}

Compiles into:

var MyClass = (function () {
    function MyClass(value) {
        this.myvariable = value;
    }
    return MyClass;
}());

As you can see, in the compiled version there's no T, so you can't use that information at runtime in order to generate a default value.


Another solution is to have a map of default values:

var defaultValues = {
    "string": "",
    "number": 0,
    "boolean": false
}

class MyClass<T> {
    myvariable: T;

    constructor(value: T) {
        this.myvariable = value;
    }
}

let a = new MyClass<string>(defaultValues.string);
let b = new MyClass<boolean>(defaultValues.boolean);

You can also use static factory methods:

class MyClass<T> {
    myvariable: T;

    constructor(value: T) {
        this.myvariable = value;
    }

    static stringInstance(): MyClass<string> {
        return new MyClass<string>("");
    }

    static numberInstance(): MyClass<number> {
        return new MyClass<number>(0);
    }

    static booleanInstance(): MyClass<boolean> {
        return new MyClass<boolean>(false);
    }
}

let a = MyClass.stringInstance();
let b = MyClass.booleanInstance();
like image 117
Nitzan Tomer Avatar answered Oct 27 '22 09:10

Nitzan Tomer