2

How can I create a generic component in Angular 2/Typescript that is capable of creating an instance of the generic-type?

@Component({
    selector: 'generic',
    template: 'generic.html'
})
export class GenericComponent<T> {
    private array: T[];

    addElement() {
        const object = new T();
        this.array.push(object);
    }
}

Currently I get an error message saying:

TS2693: 'T' only refers to a type, but is being used as a value here.

Furthermore, I should be able to specify the type somehow:

<generic ...></generic>
Bart Heyrman
  • 51
  • 1
  • 9
  • Possible duplicate of [How to create a new object from type parameter in generic class in typescript?](https://stackoverflow.com/questions/17382143/how-to-create-a-new-object-from-type-parameter-in-generic-class-in-typescript) – ᴘᴀɴᴀʏɪᴏᴛɪs Jun 12 '18 at 13:32

2 Answers2

3

Generics are erased at compile-time so you can't use the type argument T to create a new instance of T. You can however pass is a constructor of T to the class:

export class GenericComponent<T> {
    // Take the constructor of T to the component constructor
    constructor(private ctor: new ()=> T) {}
    private array: T[];

    addElement() {
        const object = new this.ctor();
        this.array.push(object);
    }
}

class Item {}
class ItemComponent extends GenericComponent<Item>{
    constructor(){
        super(Item) // Pass in the constructor of the concrete type
    }
}
Titian Cernicova-Dragomir
  • 230,986
  • 31
  • 415
  • 357
3

A working solution can be:

@Component({
    selector: 'generic',
    template: 'generic.html'
})
export class GenericComponent<T> {
    private array: T[];

    @Input() creator: { new (): T; };

    addElement() {
        const object = new this.creator;
        this.array.push(object);
    }
}

@Component({
    selector: 'parent',
    template: '<generic [creator]="itemCreator" [array]="someArray"></generic>'
})
export class ParentComponent {
    private someArray: Item[];

    @Input() itemCreator: { new (): Item; };

    constructor() {
        this.itemCreator = Item;
    }

    ngOnInit() {
        this.someArray = [];
    }
}

class Item {}

In this case, I should be able to use the generic-component for all array-like objects.

Bart Heyrman
  • 51
  • 1
  • 9