1

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?

1 Answer 1

2

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

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.