Передача класса в качестве параметра причины «не newable» ошибка

голоса
35

Я пытаюсь передать класс в качестве параметра некоторой функции, которая будет создать экземпляр этого класса и вернуть его. Вот мой код:

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

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

Когда я пытаюсь скомпилировать это, я получаю:

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

Что я делаю не так?

Если newable значение типа является конструктор объекта как я передать функции конструктора во время выполнения?

Задан 09/10/2012 в 15:30
источник пользователем
На других языках...                            


7 ответов

голоса
48

Нам нужно что-то сказать TypeOf (MyClass), чтобы отличить объекты классов сигнатуры функций.

Во всяком случае, вы можете решить вам проблему с помощью конструктора типа подписи. Учитывая этот класс:

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

Для того, чтобы пройти этот класс как тип, который вы можете создать экземпляр в функции, вы действительно должны дублировать конструктор класса подписи, как это:

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

EDIT: Существует простое решение , найденное на CodePlex:

Вы должны создать интерфейс для вашего класса, как это:

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

Затем, используйте его в вашей подписи функции:

function sample(MyClass: IMyClass) {
    var obj = new MyClass("hello");
}
Ответил 13/10/2012 в 09:45
источник пользователем

голоса
14

Попробуй это:

export class MyApp {
    registerView(viewKlass: typeof A.Views.View): void {
        var test = new viewKlass();
    } 
}
Ответил 28/06/2016 в 16:18
источник пользователем

голоса
6

Есть 2 способа пройти классы в машинописи. Если ты:

  • знать суперкласс класса вы , проходящей через (уже рекомендованные Кори Аликс):

    class MyClass extends MySuperClass{ }
    
    makeMyClass(classRef: typeof MySuperclass) {
        return new classRef();
    }
    
    makeMyClass(MyClass);
    
  • знать сигнатуру функции классов конструктора :

    class MyClass {
        constructor(arg: string) {}
    }
    
    makeMyClass(classRef: { new(arg: string) }) {
        return new classRef('hello');
    }
    
    makeMyClass(MyClass);
    
Ответил 25/04/2017 в 14:24
источник пользователем

голоса
2

Для того, чтобы дополнить другие ответы; У меня есть тип утилиты я храню вокруг, чтобы обеспечить общий параметр / поле является класс / newable:

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

Вы можете убедиться, что вы получаете конструктор класса:

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

Newable<T>подход работает , где typeof T--where Tявляется общим type-- не.

Например: register<T extends TViewBase>(view: typeof T)результаты в следующей ошибке:

[TS] «Т» относится только к типу, но в настоящее время используется в качестве значения здесь.

Ответил 31/08/2017 в 14:06
источник пользователем

голоса
2

Я знаю, что это старый вопрос, но здесь идет:

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

Ответ был найден здесь .

Ответил 02/07/2017 в 18:06
источник пользователем

голоса
0

В зависимости от ситуации, сильфон три решений не может быть достаточно:

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

Есть случаи , когда вы хотели бы вызвать некоторые статические методы , такие как myClass.someMethod(). 1и 2не позволит вам сделать это (и пожалуйста не использовать какие - либо в вашем приложении) , потому что они не знают об этом методе.

Или бывают случаи , когда вы хотите иметь в MyClassкачестве абстрактного класса и создать экземпляр MyClass с let instance = new myClass. В этом случае 3не удастся.

Что делать в таких случаях заключается в создании специального типа для , MyClassкоторый будет решать вопросы , которые я подсвеченные выше, который выглядит примерно так:

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

КСТАТИ. Не забудьте добавить типы возвращаемых в ваши методы, так что вы получите надлежащее IntelliSense.

Ответил 04/10/2019 в 18:36
источник пользователем

голоса
-1

Спасибо за суть - незначительное изменение делает все отлично работает. В приведенном ниже примере мы «новый вверх» TestViewпройти в конкретном тестовое, а не пытаться его новым в методе.

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())
Ответил 09/10/2012 в 16:09
источник пользователем

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