208 votes

Créer un nouvel objet à partir d'un paramètre de type dans une classe générique

J'essaie de créer un nouvel objet d'un paramètre de type dans ma classe générique. Dans ma classe View J'ai 2 listes d'objets de type générique passés comme paramètres de type, mais quand j'essaie de faire de la new TGridView() TypeScript dit :

Impossible de trouver le symbole 'TGridView

Voici le code :

module AppFW {
    // Represents a view
    export class View<TFormView extends FormView, TGridView extends GridView> {
        // The list of forms 
        public Forms: { [idForm: string]: TFormView; } = {};

        // The list of grids
        public Grids: { [idForm: string]: TGridView; } = {};

        public AddForm(formElement: HTMLFormElement, dataModel: any, submitFunction?: (e: SubmitFormViewEvent) => boolean): FormView {
            var newForm: TFormView = new TFormView(formElement, dataModel, submitFunction);
            this.Forms[formElement.id] = newForm;
            return newForm;
        }

        public AddGrid(element: HTMLDivElement, gridOptions: any): GridView {
            var newGrid: TGridView = new TGridView(element, gridOptions);
            this.Grids[element.id] = newGrid;
            return newGrid;
        }
    }
}

Puis-je créer des objets à partir d'un type générique ?

201voto

blorkfish Points 2107

Pour créer un nouvel objet dans un code générique, vous devez faire référence au type par sa fonction de construction. Ainsi, au lieu d'écrire ceci

function activatorNotWorking<T extends IActivatable>(type: T): T {
    return new T(); // compile error could not find symbol T
}

Tu dois écrire ça :

function activator<T extends IActivatable>(type: { new(): T ;} ): T {
    return new type();
}

var classA: ClassA = activator(ClassA);

Voir cette question : Inférence de type générique avec argument de classe

120voto

Steve Fenton Points 55265

Parce que le JavaScript compilé a toutes les informations de type effacées, vous ne pouvez pas utiliser la fonction T pour mettre à jour un objet.

Vous pouvez le faire d'une manière non générique en passant le type dans le constructeur.

class TestOne {
    hi() {
        alert('Hi');
    }
}

class TestTwo {
    constructor(private testType) {

    }
    getNew() {
        return new this.testType();
    }
}

var test = new TestTwo(TestOne);

var example = test.getNew();
example.hi();

Vous pourriez étendre cet exemple en utilisant des génériques pour resserrer les types :

class TestBase {
    hi() {
        alert('Hi from base');
    }
}

class TestSub extends TestBase {
    hi() {
        alert('Hi from sub');
    }
}

class TestTwo<T extends TestBase> {
    constructor(private testType: new () => T) {
    }

    getNew() : T {
        return new this.testType();
    }
}

//var test = new TestTwo<TestBase>(TestBase);
var test = new TestTwo<TestSub>(TestSub);

var example = test.getNew();
example.hi();

48voto

TadasPa Points 461

Toutes les informations sur le type sont effacées du côté JavaScript et donc vous ne pouvez pas créer un nouveau T comme le dit @Sohnee, mais je préférerais avoir un paramètre typé passé dans le constructeur :

class A {
}

class B<T> {
    Prop: T;
    constructor(TCreator: { new (): T; }) {
        this.Prop = new TCreator();
    }
}

var test = new B<A>(A);

21voto

Jazib Points 1165

Je sais qu'il est tard mais la réponse de @TadasPa peut être ajustée un peu en utilisant

TCreator: new() => T

au lieu de

TCreator: { new (): T; }

donc le résultat devrait ressembler à ceci

class A {
}

class B<T> {
    Prop: T;
    constructor(TCreator: new() => T) {
        this.Prop = new TCreator();
    }
}

var test = new B<A>(A);

13voto

jalescardoso Points 146
export abstract class formBase<T> extends baseClass {

  protected item = {} as T;
}

Son objet pourra recevoir n'importe quel paramètre, cependant, le type T n'est qu'une référence typographique et ne peut être créé par un constructeur. En d'autres termes, il ne créera pas d'objets de classe.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X