Przechodząc klasy jako przyczyny parametr „nie jest odnawialny” błąd

głosy
35

Próbuję przekazać klasę jako parametr do niektórych funkcji, które będą instancję tej klasy i zwraca go. Tu jest mój kodu:

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

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

Kiedy próbuję skompilować ten, Dostaję:

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

Co ja robię źle?

Jeśli odnawialny wartość typ jest konstruktor obiektu jak mogę przekazać funkcję konstruktora w czasie wykonywania?

Utwórz 09/10/2012 o 15:30
źródło użytkownik
W innych językach...                            


7 odpowiedzi

głosy
48

Musimy coś powiedzieć typeof (MyClass) rozróżnić obiekty z klas w podpisach funkcyjnych.

W każdym razie, rzeczywiście można rozwiązać Ci problem za pomocą konstruktora typu podpis. Biorąc pod uwagę tę klasę:

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

Aby przekazać tę klasę jako typ, który można następnie instancję w funkcji, trzeba rzeczywiście powielać podpis konstruktora klasy tak:

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

EDIT: Jest to proste rozwiązanie znaleźć na CodePlex:

Musisz utworzyć interfejs dla swojej klasy jak poniżej:

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

Następnie użyj go w podpisie funkcji:

function sample(MyClass: IMyClass) {
    var obj = new MyClass("hello");
}
Odpowiedział 13/10/2012 o 09:45
źródło użytkownik

głosy
14

Spróbuj tego:

export class MyApp {
    registerView(viewKlass: typeof A.Views.View): void {
        var test = new viewKlass();
    } 
}
Odpowiedział 28/06/2016 o 16:18
źródło użytkownik

głosy
6

Istnieją 2 sposoby, aby zdać zajęcia w maszynopisie. Jeśli ty:

  • znać nadklasą klasie jesteś przejazdem (już zalecany przez Corey Alix):

    class MyClass extends MySuperClass{ }
    
    makeMyClass(classRef: typeof MySuperclass) {
        return new classRef();
    }
    
    makeMyClass(MyClass);
    
  • znać sygnaturę funkcji konstruktora klasy :

    class MyClass {
        constructor(arg: string) {}
    }
    
    makeMyClass(classRef: { new(arg: string) }) {
        return new classRef('hello');
    }
    
    makeMyClass(MyClass);
    
Odpowiedział 25/04/2017 o 14:24
źródło użytkownik

głosy
2

W celu uzupełnienia innych odpowiedzi; Mam typ użytkowy trzymam wokół celu zapewnienia parametru rodzajowego / pole jest klasą / odnawialny:

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

Następnie można zapewnić Ci konstruktora klasy:

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

Newable<T>podejście działa gdzie typeof T--where Tjest ogólnym type-- nie.

Na przykład: register<T extends TViewBase>(view: typeof T)wyniki w następujący błąd:

[Ts] „T” odnosi się tylko do typu, ale jest stosowany jako wartość tutaj.

Odpowiedział 31/08/2017 o 14:06
źródło użytkownik

głosy
2

Wiem, że jest to stara sprawa, ale tu idzie:

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

Odpowiedź została znaleziona tutaj .

Odpowiedział 02/07/2017 o 18:06
źródło użytkownik

głosy
0

W zależności od sytuacji, poniżej trzy rozwiązanie nie może być za mało:

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

Istnieją przypadki, gdzie chcesz zadzwonić kilka statycznych metod, takich jak myClass.someMethod(). 1i 2nie pozwoli, aby to zrobić (i nie używać żadnych pls w aplikacji), ponieważ nie wiedzą o tej metodzie.

Czy istnieją przypadki, gdy chcesz mieć MyClassjako abstrakcyjnej klasy i utworzyć instancję MojaKlasa z let instance = new myClass. W tym przypadku 3nie zadziała.

Co zrobić w takich przypadkach jest utworzenie specjalnego typu na MyClassktóry rozwiąże problemy I podkreślona powyżej, który wygląda mniej więcej tak:

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

BTW. Nie zapomnij dodać typy powrócić do metod więc masz prawidłowe intellisense.

Odpowiedział 04/10/2019 o 18:36
źródło użytkownik

głosy
-1

Dziękuję za GIST - nieznaczna zmiana sprawia, że wszystko działa prawidłowo. W poniższym przykładzie, „nowa góry” TestView, aby przejść na betonowej widzenia testu, zamiast próbować go w nowy sposób.

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())
Odpowiedział 09/10/2012 o 16:09
źródło użytkownik

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