Passerer klasse som parameter årsaker "er ikke newable" feil

stemmer
36

Jeg prøver å passere en klasse som en parameter til noen funksjon, som vil instantiate denne klassen og returnere den. Her er min kode:

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

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

Når jeg prøver å kompilere dette, jeg får:

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

Hva gjør jeg galt?

Hvis en newable typeverdi er et objekt konstruktør hvordan kan jeg passere konstruktørfunksjon under kjøring?

Publisert på 09/10/2012 klokken 14:30
kilden bruker
På andre språk...                            


7 svar

stemmer
55

Vi trenger noe å si typeof (MyClass) for å skille objekter fra klasser i funksjons signaturer.

Uansett, du kan faktisk løse du problemet ved å bruke konstruktøren typen signatur. Vurderer denne klassen:

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

Å passere den klassen som en type som du deretter kan instantiate i en funksjon, du faktisk nødt til å duplisere klassen konstruktør signatur som dette:

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

EDIT: Det er en enkel løsning funnet på CodePlex:

Du må lage et grensesnitt for klassen din som dette:

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

Deretter bruker den i funksjon signatur:

function sample(MyClass: IMyClass) {
    var obj = new MyClass("hello");
}
Svarte 13/10/2012 kl. 08:45
kilden bruker

stemmer
14

Prøv dette:

export class MyApp {
    registerView(viewKlass: typeof A.Views.View): void {
        var test = new viewKlass();
    } 
}
Svarte 28/06/2016 kl. 16:18
kilden bruker

stemmer
6

Det er 2 måter å passere klasser i Loggfila. Hvis du:

  • vet super av klassen du passerer gjennom (allerede anbefalt av Corey Alix):

    class MyClass extends MySuperClass{ }
    
    makeMyClass(classRef: typeof MySuperclass) {
        return new classRef();
    }
    
    makeMyClass(MyClass);
    
  • vet underskrift av klassene konstruktør funksjon :

    class MyClass {
        constructor(arg: string) {}
    }
    
    makeMyClass(classRef: { new(arg: string) }) {
        return new classRef('hello');
    }
    
    makeMyClass(MyClass);
    
Svarte 25/04/2017 kl. 14:24
kilden bruker

stemmer
3

For å supplere de andre svarene; Jeg har en nytte type I holder rundt for å sikre en generell parameter / felt er en klasse / newable:

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

Du kan deretter sikre at du får en klasse konstruktør:

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

den Newable<T>tilnærmingen fungerer der typeof T--where Ter en generisk type-- ikke.

For eksempel: register<T extends TViewBase>(view: typeof T)gir følgende feilmelding:

[Ts] 'T' bare refererer til en type, men blir brukt som en verdi her.

Svarte 31/08/2017 kl. 14:06
kilden bruker

stemmer
3

Jeg vet dette er en gammel spørsmålet, men her går:

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

Svaret ble funnet her .

Svarte 02/07/2017 kl. 18:06
kilden bruker

stemmer
0

Avhengig av situasjonen, kan de tre løsning Bellow ikke være nok:

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

Det finnes tilfeller der du ønsker å ringe noen statiske metoder som myClass.someMethod(). 1og 2vil ikke tillate deg å gjøre det (og pls bruker aldri noen i din app), fordi de ikke vet om denne metoden.

Eller det finnes tilfeller der du ønsker å ha MyClasssom en abstrakt klasse og opprette en forekomst av MyClass med let instance = new myClass. I så fall 3vil mislykkes.

Hva jeg gjør i disse tilfellene er å skape en spesiell type for MyClasssom vil løse problemene jeg uthevet ovenfor, som ser omtrent slik ut:

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

BTW. Ikke glem å legge returtyper til metoder slik at du får riktig IntelliSense.

Svarte 04/10/2019 kl. 18:36
kilden bruker

stemmer
-1

Takk for hovedpunkt - en liten endring som gjør det hele fungerer fint. I eksempelet nedenfor har vi "nye opp" TestViewtil å passere i betong test syn, heller enn å prøve å nytt det innen metoden.

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())
Svarte 09/10/2012 kl. 15:09
kilden bruker

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