93 votes

Le passage d'une classe en tant que paramètre provoque l'erreur "is not newable".

J'essaie de passer une classe comme paramètre à une fonction qui instancie cette classe et la renvoie. Voici mon code :

module A.Views {
  export class View { ... }
}

module A.App {
  export class MyApp {
    ...
    registerView(viewKlass:A.Views.View):void
    {
        var test = new viewKlass;
    } 
  }
}

Quand j'essaye de compiler ceci, j'obtiens :

(...): Value of type 'Views.View' is not newable.

Qu'est-ce que je fais de mal ?

Si une valeur de type newable est un constructeur d'objet, comment puis-je passer la fonction du constructeur au moment de l'exécution ?

3voto

Perspectivus Points 844

Je sais que c'est une vieille question, mais je vais la poser :

...
registerView(viewKlass: { new(): A.Views.View }):void
{
    var test = new viewKlass();
} 

La réponse a été trouvée aquí .

3voto

boyd Points 481

Selon votre situation, les trois solutions ci-dessous peuvent ne pas être suffisantes :

  1. myClass: new (name: string) => MyClass
  2. interface IMyClass { new (name: string): MyClass; }; myClass: IMyClass
  3. myClass: typeof MyClass

Il y a des cas où vous voudriez appeler certains statique des méthodes comme myClass.someMethod() . 1 y 2 ne vous permettront pas de le faire (et n'en utilisez jamais dans votre application) car ils ne connaissent pas cette méthode.

Ou il y a des cas où vous voulez avoir MyClass comme un abstrait et créer une instance de myClass avec let instance = new myClass . Dans ce cas, 3 échouera.

Ce que je fais dans ces cas est de créer un type spécial pour les MyClass qui résoudra les problèmes que j'ai soulignés ci-dessus, qui ressemble à quelque chose comme ceci :

type MyClassContructor<T extends MyClass> = typeof MyClass & Constructor<T>;

BTW. N'oubliez pas d'ajouter des types de retour à vos méthodes afin d'obtenir un intellisense correct.

-1voto

Steve Fenton Points 55265

Merci pour l'essentiel - un léger changement fait que tout fonctionne bien. Dans l'exemple ci-dessous, nous avons "relooké" la fonction TestView pour passer dans la vue de test concrète, plutôt que d'essayer de le faire dans la méthode.

module V.Views {
   export class View {
      public someVar: any;
      // the presence of constructor doesn't affect the error triggering
   }
}

module V.App {
    export class Application {
        public registerView(url: string, viewKlass: V.Views.View): void
        {
            var test = viewKlass;
        }
    }
}

var app = new V.App.Application;

class TestView extends V.Views.View {
}

class TestView2 extends V.Views.View {
}

app.registerView('', new TestView())
app.registerView('content/view/:slug/', new TestView2())

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