Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Instantiating Generic Types

Given the following class:

class Datum {}

I get an error message (error TS2304: Cannot find name 'T') when I try to do the following:

class Data<T extends Datum> {
    datum: T

    constructor() {
        this.datum = new T()
    }
}

So then I try doing this, but I also get an error message (Type 'Datum' is not assignable to type 'T'):

 class Data<T extends Datum> {
    datum: T

    constructor() {
        this.datum = new Datum();
    }
}

Question: Is it not possible to instantiate the constrained type T? My assumption was that since T is constrained such that it must extend Datum, I'd be able to do datum: T = new Datum().

like image 517
Andre Gregori Avatar asked Aug 03 '15 17:08

Andre Gregori


1 Answers

Two things to remember: First, generics are erased during compilation. They have no runtime impact, so any attempt to reference a generic type as if it were a runtime value has no meaning.

Second, it's possible for a derived class of Datum to have constructor parameters. Even if T did exist, you can't just blindly new it with zero arguments.

Putting that together, what you want is this:

class Datum {}

class Data<T extends Datum> {
    datum: T

    constructor(ctor: new() => T) {
        this.datum = new ctor();
    }
}

class ByteDatum extends Datum {
    new() { }
}

let y = new Data(ByteDatum);
let x = y.datum; // x: ByteDatum
like image 76
Ryan Cavanaugh Avatar answered Nov 15 '22 04:11

Ryan Cavanaugh