简体   繁体   中英

TypeScript generic function creating new instance with parameter

I have many classes extending an interface. These classes can have arrays containg objects of each other. So for instance: A school can contain many studens but both implements the same interface.

I've create a generic function for this instead of using every time a forEach loop and pushing them to the array. This new generic function should do this for me with a single line.

export class School implements MyInterface {
    public studens: Student[] = [];
    public constructor(data_from_backend) {
        this.students = mapDataToModelArrayFunction<Student>(data_from_backend.students);
    }
}

export class Student implements MyInterface {
    public name: string;
    public constructor(data_from_backend) {
        this.name = data_from_backend.name;
    }
}

export function mapDataToModelArrayFunction<T>(array): T[] {
    const listToReturn: T[] = [];
    if (Array.isArray(array)) {
        array.forEach(item => {
            listToReturn.push(new T(obj));
        });
    }
    return listToReturn;
}

But TypeScript/Angular is giving me an error because of the T. I'm not allowed to create an instance of T. So how can I do this?

Types do not exist at runtime so T is erased and the expression new T(item) turns into new (item) which does not really make sense. Or another way of saying this, you can't use types in expressions.

The solution is to pass in a constructor function (ie the class) into your mapping function:

interface MyInterface { }
export class School implements MyInterface {
    public students: Student[] = [];
    public constructor(data_from_backend: any) {
        this.students = mapDataToModelArrayFunction(Student, data_from_backend.students);
    }
}

export class Student implements MyInterface {
    public name: string;
    public constructor(data_from_backend: any) {
        this.name = data_from_backend.name;
    }
}

export function mapDataToModelArrayFunction<T>(cls: new (data: any) => T, array: any[]): T[] {
    const listToReturn: T[] = [];
    if (Array.isArray(array)) {
        array.forEach(item => {
            listToReturn.push(new cls(item));
        });
    }
    return listToReturn;
}

Play

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM