CollectionResult <T>в машинописном тексте - PullRequest
2 голосов
/ 27 мая 2019

Я пытаюсь создать универсальный класс для прокси-сервиса, который получает ответ от сервера.Когда я остаюсь, чтобы реализовать этот класс, у меня возникает проблема - вызвать метод из универсального класса.Как я могу вызвать статический метод изJs (item), который объявлен в универсальном типе?

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>;
}

// Универсальный класс, который передается в 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;
}

// Использование в прокси-методах

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>());
    }

1 Ответ

0 голосов
/ 27 мая 2019

Вы не можете получить доступ к элементам параметра общего типа. Параметры типа стираются во время компиляции, поэтому вы не можете зависеть от них ни для чего, кроме проверки типов.

Вы можете передать класс как параметр и ограничить использование метода fromJs:

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());
...