Reputation: 1041
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..
Upvotes: 10
Views: 12821
Reputation: 164139
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";
}
}
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();
Upvotes: 12
Reputation: 16205
Well I guess I came up with a possible solution. Anyway I must say that Nitzan Tomer is right and the class type is not available in runtime. This is the funny side of TS :)
Here you can check the type of the objects you get in and then set a default value. You could also change the place and the objects to check in order to do it the way you want but I guess it could be a good starting point for you. Notice that you have to do a double cast because TS cannot guarantee that types are compatible. I haven't tried it yet but it compiles well
class MyClass<T>{
myvariable: T
constructor(param: any) {
if (typeof param === 'string') {
this.myvariable = <T><any> "";
}
else if (typeof param === 'number') {
this.myvariable = <T><any> 0;
}
}
}
Upvotes: 0
Reputation: 4019
T
is lost at runtime, so you need to pass in the type like a value. And you can do that by passing the constructor.
When I have a similar need, I usually use an interface like this:
interface Type<T> {
new() : T;
}
And create MyClass like so:
class MyClass<T>{
myvariable: T;
constructor(type: Type<T>) {
this.myvariable = new type();
}
}
Then I can use MyClass like so:
let myinstance = new MyClass(TheOtherType);
It works for classes, but not for built-ins like string and number.
TheOtherType
is the constructor of a class such as:
class TheOtherType {
}
Upvotes: 0