TypeScript: pass generic type as parameter in generic class

30,615

Solution 1

Generics are just metadata. They cannot be used as parameters when calling a function. Maybe you need something like this:

export class ViewModelBase<T extends DataObject> {
  constructor(private Cl: {new(): T}) {
  }
  public getData(): Array<T> {
    return DataProvider.getTableData<T>(this.Cl);
  }
}

Solution 2

maybe this would help:

export abstract class BaseEntity {
  public static from<T extends BaseEntity>(c: new() => T, data: any): T {
    return Object.assign(new c(), data)
  }
  public static first<T extends BaseEntity>(c: new() => T, data) {
    if (data.rows.length > 0) {
      let item = data.rows.item(0);
      return BaseEntity.from(c, item);
    }
    return null;
  }

}

This class can be extended by others so you could call methods on the base class or on its subclasses.

For instance:

return Product.first(Product, data);

Or:

return BaseEntity.first(Product, data);

See how from() method is called from inside first()

Share:
30,615

Related videos on Youtube

Bronco Oostermeyer
Author by

Bronco Oostermeyer

Updated on July 09, 2022

Comments

  • Bronco Oostermeyer
    Bronco Oostermeyer almost 2 years

    TypeScript: I have a method in the DataProvider class with a method getTableData:

    public static getTableData<T extends DataObject>(type: { new(): T}): Array<T> { ... }
    

    this works perfectly when I code:

    let speakers = DataProvider.getTableData(Speaker);  // where Speaker is a class
    

    now I want to call this from a generic Class:

    export class ViewModelBase<T extends DataObject> {   
      public getData(): Array<T> {
        return <T[]> DataProvider.getTableData(T);
      }
    }
    

    Now I get a Cannot find name 'T' error for the T parameter I pass to getTableData. How should getTableData be called?

    update: With the help of @Paleo I came up this:

    export class ViewModelBase<T extends DataObject> {   
    
      constructor(private dataObjectClass: { new(): T}){}
    
      public getTableData(): Array<T> {
        return <T[]> DataProvider.getTableData<T>(this.dataObjectClass);
      }
    }
    

    the thing is that although I have already told in: class SpeakerViewModel extends ViewModelBase<Speaker> { ... } that I want it to be a ViewModel for Speaker I still have the instantiate the SpeakerViewModel like:

    let vm = new SpeakerViewModel(Speaker);

    although I have already told it is all about Speaker. I guess I still don't fully understand this.

  • Bronco Oostermeyer
    Bronco Oostermeyer almost 8 years
    almost but your comment made me figure what I actually needed: constructor(private Cl: { new(): T}).... Thanks!
  • Paleo
    Paleo almost 8 years
    @BroncoOostermeyer OK. I edited to fix the code for future readers.

Related