Reputation: 580
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.
Upvotes: 16
Views: 53743
Reputation: 259
How about defining a base type and extending it? Then your function could expect the base type, and you could call it with the extended type. e.g:
export interface BaseData {
key: object
}
Then:
import { BaseData } from 'baseDataFile'
export interface DerivedData extends BaseData {
key: someObjectType
}
Now:
import { BaseData } from 'baseDataFile'
export const someFunc = (props: BaseData) => {
// do some stuff
return something
}
Finally:
import { DerivedData } from 'derivedDataFile'
const myData: DerivedData = something as DerivedData
const myNewData = someFunc(myData)
Upvotes: -2
Reputation: 511
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()
Upvotes: 3
Reputation: 23692
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);
}
}
Upvotes: 6