classe comme causes de passage paramètre «n'est pas newable » erreur

voix
35

Je suis en train de passer une classe en tant que paramètre à une fonction, qui instancier cette classe et le retourner. 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 je suis en train de compiler, je reçois:

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

Qu'est-ce que je fais mal?

Si une valeur de type newable est un constructeur d'objet comment passe je ne la fonction constructeur lors de l'exécution?

Créé 09/10/2012 à 15:30
source utilisateur
Dans d'autres langues...                            


7 réponses

voix
48

Nous avons besoin de quelque chose à dire typeof (MyClass) pour distinguer les objets des classes dans les signatures de fonction.

Quoi qu'il en soit, vous pouvez réellement vous résoudre le problème en utilisant la signature de type constructeur. Compte tenu de cette classe:

class MyClass {
    constructor (private name: string) {
    }
}

Pour passer cette classe comme un type que vous pouvez instancier dans une fonction, vous avez fait de dupliquer la signature du constructeur de la classe comme ceci:

function sample(MyClass: new (name: string) => MyClass) {
    var obj = new MyClass("hello");
}

EDIT: Il y a une solution simple trouvée sur CodePlex:

Vous devez créer une interface pour votre classe comme ceci:

interface IMyClass {
    new (name: string): MyClass;
}

Ensuite, utilisez dans votre signature de la fonction:

function sample(MyClass: IMyClass) {
    var obj = new MyClass("hello");
}
Créé 13/10/2012 à 09:45
source utilisateur

voix
14

Essaye ça:

export class MyApp {
    registerView(viewKlass: typeof A.Views.View): void {
        var test = new viewKlass();
    } 
}
Créé 28/06/2016 à 16:18
source utilisateur

voix
6

Il y a 2 façons de passer des classes dactylographiée. Si vous:

  • connaître la superclasse de la classe vous en passant par (déjà recommandé par Corey Alix):

    class MyClass extends MySuperClass{ }
    
    makeMyClass(classRef: typeof MySuperclass) {
        return new classRef();
    }
    
    makeMyClass(MyClass);
    
  • connaître la signature de la fonction constructeur classes :

    class MyClass {
        constructor(arg: string) {}
    }
    
    makeMyClass(classRef: { new(arg: string) }) {
        return new classRef('hello');
    }
    
    makeMyClass(MyClass);
    
Créé 25/04/2017 à 14:24
source utilisateur

voix
2

Pour compléter les autres réponses; J'ai un type utilitaire je garde autour d'assurer un paramètre générique / champ est une classe / newable:

/* new T() */
export type Newable<T> = { new (...args: any[]): T; };

Vous pouvez alors vous assurer d'obtenir un constructeur de classe:

class MyApp<TViewBase>
{
  register<TView extends TViewBase>(view: Newable<TView>) { 
  }
}

l' Newable<T>approche fonctionne où typeof T--where Test un bien-- générique ne fonctionne pas.

Par exemple: les register<T extends TViewBase>(view: typeof T)résultats de l'erreur suivante:

[Ts] « T » se réfère uniquement à un type, mais est utilisé comme valeur ici.

Créé 31/08/2017 à 14:06
source utilisateur

voix
2

Je sais que c'est une vieille question, mais voilà:

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

Réponse a été trouvée ici .

Créé 02/07/2017 à 18:06
source utilisateur

voix
0

En fonction de votre situation, ci-dessous trois solution pourrait ne pas suffire:

  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 souhaitez appeler quelques statiques des méthodes telles que myClass.someMethod(). 1et 2ne vous permettra pas de le faire (et pls ne jamais utiliser dans votre application) parce qu'ils ne savent pas cette méthode.

Ou il y a des cas où vous voulez avoir MyClasscomme abstraite classe 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 MyClassqui permettra de résoudre les problèmes que je souligné ci - dessus, qui ressemble à ceci:

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

BTW. Ne pas oublier d'ajouter les types de retour à vos méthodes afin que vous obtenez IntelliSense approprié.

Créé 04/10/2019 à 18:36
source utilisateur

voix
-1

Merci pour l'essentiel - une légère modification rend tout travail très bien. Dans l'exemple ci - dessous, nous « nouveau » la TestViewde passer dans la vue de test concret, plutôt que d' essayer de nouveau il 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())
Créé 09/10/2012 à 16:09
source utilisateur

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more