Classe passando come parametro cause "non è newable" Errore

voti
35

Sto cercando di passare una classe come parametro di una funzione, che un'istanza di questa classe e restituirlo. Ecco il mio codice:

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

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

Quando sto cercando di compilare questo, sto ottenendo:

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

Che cosa sto facendo di sbagliato?

Se un valore di tipo newable è un costruttore di oggetto come faccio passare la funzione di costruzione in fase di esecuzione?

È pubblicato 09/10/2012 alle 15:30
fonte dall'utente
In altre lingue...                            


7 risposte

voti
48

Abbiamo bisogno di qualcosa da dire typeof (MyClass) per distinguere gli oggetti da classi nelle firme di funzione.

In ogni caso, si può effettivamente si risolvere il problema utilizzando tipo di costruttore di firma. Considerando questa classe:

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

Per superare questa classe come un tipo che è quindi possibile creare un'istanza in una funzione, in realtà si deve duplicare la firma costruttore di classe in questo modo:

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

EDIT: C'è una soluzione semplice trovato su CodePlex:

È necessario creare un'interfaccia per la classe in questo modo:

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

Poi, utilizzarlo nella tua firma funzione:

function sample(MyClass: IMyClass) {
    var obj = new MyClass("hello");
}
Risposto il 13/10/2012 a 09:45
fonte dall'utente

voti
14

Prova questo:

export class MyApp {
    registerView(viewKlass: typeof A.Views.View): void {
        var test = new viewKlass();
    } 
}
Risposto il 28/06/2016 a 16:18
fonte dall'utente

voti
6

Ci sono 2 modi per passare le classi a macchina. Se tu:

  • conoscere la superclasse della classe che stai passando attraverso (già raccomandato da Corey Alix):

    class MyClass extends MySuperClass{ }
    
    makeMyClass(classRef: typeof MySuperclass) {
        return new classRef();
    }
    
    makeMyClass(MyClass);
    
  • conoscere la firma della funzione di classi di costruzione :

    class MyClass {
        constructor(arg: string) {}
    }
    
    makeMyClass(classRef: { new(arg: string) }) {
        return new classRef('hello');
    }
    
    makeMyClass(MyClass);
    
Risposto il 25/04/2017 a 14:24
fonte dall'utente

voti
2

Per integrare le altre risposte; Ho un tipo di utilità tengo in giro per garantire un parametro generico / campo è una classe / newable:

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

È quindi possibile essere sicuri di ottenere un costruttore della classe:

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

l' Newable<T>approccio funziona dove typeof T--where Tè un type-- generico non.

Per esempio: register<T extends TViewBase>(view: typeof T)risultati nel seguente errore:

[Ts] 'T' si riferisce solo a un tipo, ma viene utilizzato come valore qui.

Risposto il 31/08/2017 a 14:06
fonte dall'utente

voti
2

So che questa è una vecchia questione, ma qui va:

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

Risposta è stata trovata qui .

Risposto il 02/07/2017 a 18:06
fonte dall'utente

voti
0

A seconda della situazione, il soffietto tre soluzione potrebbe non essere sufficiente:

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

Ci sono casi in cui si desidera chiamare alcuni statici metodi come myClass.someMethod(). 1e 2non permetterà di farlo (e pls non usare mai alcun nella vostra app), perché non sanno di quel metodo.

Oppure ci sono casi in cui si desidera avere MyClasscome un abstract di classe e creare un'istanza di myClass con let instance = new myClass. In tal caso, 3non riuscirà.

Quello che faccio in questi casi è quello di creare un tipo speciale per MyClassche risolverà i problemi che ho sottolineato in precedenza, che sembra qualcosa di simile:

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

BTW. Non dimenticate di aggiungere tipi restituiti ai vostri metodi in modo da ottenere una corretta IntelliSense.

Risposto il 04/10/2019 a 18:36
fonte dall'utente

voti
-1

Grazie per la sostanza - un leggero cambiamento rende tutto bene il lavoro. Nell'esempio che segue, noi "nuovo" il TestViewdi passare nella vista di prova concreta, piuttosto che cercare di nuovo all'interno del metodo.

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())
Risposto il 09/10/2012 a 16:09
fonte dall'utente

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