angular - CollectionResult<T> i typescript
Jag försöker skapa en generisk klass för en proxy-tjänst som får ett svar från servern. När jag försöker implementera denna klass får jag ett problem med att anropa en metod från den generiska klassen. Hur kan jag anropa den statiska metoden fromJs(item) som deklarerats i den generiska typen?
export class CollectionResult<T> implements ICollectionResult<T> {
items: Array<T>;
constructor(data?: T) {
if (data) {
for (var property in data) {
if (data.hasOwnProperty(property))
(<any>this)[property] = (<any>data)[property];
}
}
}
init(data?: any) {
if (data) {
Object.assign(this, data);
this.items = [];
for (let item of data.items) {
this.items.push(T//NOTE: Error here//.fromJS(item));
}
}
}
fromJS(data: any): CollectionResult<T> {
let result = new CollectionResult<T>();
result.init(data);
return result;
}
toJSON(data?: any) {
data = typeof data === 'object' ? data : {};
Object.assign(data, this);
if (this.items && this.items.constructor === Array) {
data["items"] = [];
for (let item of this.items) {
data["items"].push(item);
}
}
return data;
}
}
export interface ICollectionResult<T> {
items: Array<T>;
}
// Generisk klass som skickas in i CollectionResult
export class ProgramDto implements
IProgramDto {
year: number;
month: number;
accounts: number;
constructor(data?: ProgramDto) {
if (data) {
for (var property in data) {
if (data.hasOwnProperty(property))
(<any>this)[property] = (<any>data)[property];
}
}
}
init(data?: any) {
if (data) {
Object.assign(this, data);
}
}
static fromJS(data: any): ProgramDto {
let result = new ProgramDto();
result.init(data);
return result;
}
toJSON(data?: any) {
data = typeof data === 'object' ? data : {};
Object.assign(data, this);
return data;
}
}
export interface IProgramDto {
year: number;
month: number;
accounts: number;
}
//Användning i proxymetoder
Get(): Observable<CollectionResult<ProgramDto >> {
let url = `${this.baseUrl}/Api/Controller/Method`;
url = url.replace(/[?&]$/, "");
let options = this.getOptions();
return this.sendRequestWithResponse(url, options, CollectionResult<ProgramDto>.fromJS, new CollectionResult<ProgramDto>());
}
Svar #1
Du kan inte komma åt medlemmar av en generisk typparameter. Typparametrar tas bort under kompilering, så du kan inte förlita dig på dem för något annat än typkontroll.
Du kan skicka in klassen som en parameter och begränsa den till att ha fromJs-metoden:
type CollectionResultDataClass<T> = {
new(...a: any[]): T
fromJs(o: any): T
}
export class CollectionResult<T> implements ICollectionResult<T> {
items: Array<T>;
constructor(private cls: CollectionResultDataClass<T>, data?: T) {
// ...
}
init(data?: any) {
if (data) {
Object.assign(this, data);
this.items = [];
for (let item of data.items) {
this.items.push(this.cls.fromJs(item));
}
}
}
fromJS(data: any): CollectionResult<T> {
let result = new CollectionResult<T>(this.cls);
result.init(data);
return result;
}
toJSON(data?: any) {
//..
}
}
//Usage
class MyDataClass {
static fromJs(o: any) {
return Object.assign(new MyDataClass(), o);
}
}
new CollectionResult(MyDataClass, new MyDataClass());
