typescript - At videregive klasse som parameter forårsager fejlen "kan ikke instantieres"


Jeg prøver at videregive en klasse som en parameter til en funktion, der vil instantierer denne klasse 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 forsøger at kompilere dette, får jeg:

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

Hvad gør jeg forkert?

Hvis en fornybar typeværdi er en objektkonstruktør, hvordan passer jeg konstruktørfunktionen ved kørselstid?

Svar #1

Vi har brug for noget at sige typeof(MyClass) for at skelne objekter fra klasser i funktionssignaturer.

Under alle omstændigheder kan du faktisk løse dit problem ved at bruge konstruktørens typesignatur. Med denne klasse:

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

For at passere den klasse som en type, som du derefter kan instantierer i en funktion, skal du faktisk duplikere klassens konstruktørsignatur på denne måde:

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

REDIGER: Der er en simpel løsning fundet på codeplex:

Du skal oprette en grænseflade for din klasse som dette:

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

Brug det derefter i din funktionssignatur:

function sample(MyClass: IMyClass) {
    var obj = new MyClass("hello");
}

Svar #2

For at supplere de andre svar; jeg har en hjælpe-type, jeg holder omkring for at sikre, at en generisk parameter/felt er en klasse/kan instansieres:

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

Du kan derefter sikre dig, at du får en klassekonstruktør:

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

tilgangen Newable<T> fungerer, hvor typeof T -- hvor T er en generisk type -- ikke gør.

For eksempel: register<T extends TViewBase>(view: typeof T) resulterer i følgende fejl:

>> [ts] 'T' only refers to a type, but is being used as a value here.

Svar #3

Prøv dette:

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

Svar #4

Der er 2 måder at passere klasser på i TypeScript. Hvis du:

  • kend superklassen til den klasse, du passerer igennem (allerede anbefalet af Corey Alix):

    class MyClass extends MySuperClass{ }
    
    makeMyClass(classRef: typeof MySuperclass) {
        return new classRef();
    }
    
    makeMyClass(MyClass);
    
  • kender signaturen på klassens konstruktørfunktion:

    class MyClass {
        constructor(arg: string) {}
    }
    
    makeMyClass(classRef: { new(arg: string) }) {
        return new classRef('hello');
    }
    
    makeMyClass(MyClass);
    

Svar #5

hvis du bruger Angular, har de implementeret Type, det ligner Meirion Hughes' svar:

import {Type} from '@angular/core';

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

Relaterede artikler