2016-06-06 2 views
1

У меня есть приложение, которое инициализирует, запустив его метод .init(params) так:Как ввести массив с классами в TypeScript?

app.init([TopBar, StatusBar, MainArea]); 

Где TopBar, StatusBar и MainArea классы, а не экземпляры классов. Каждый из этих классов реализует один и тот же интерфейс IComponent.

Я хочу, чтобы создавать объекты из пройденных классов в методе .init(params), как это:

init(params: IComponent[]): void { 
    params.map(function (component) { 
     let comp = new component(); 
     this.components[comp.constructor.name] = comp; 
    }, this); 

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

error TS2345: Argument of type '(typeof TopBar | typeof StatusBar | typeof MainArea)[]' is not assignable to parameter of type 'IComponent[]'.

Как исправить код, чтобы я мог передать массив классов, реализующих некоторый интерфейс для метода?

+0

Почему бы не использовать функцию заводскую вместо того, чтобы использовать новый в классе? – davestevens

ответ

1

Там есть working typescript playground (запустить его, чтобы получить уведомление с результатом)

что нам нужно для создания пользовательского type InterfaceComponent. Это будет ожидаться как массив метода init()

interface IComponent { } 
class TopBar implements IComponent { } 
class StatusBar implements IComponent { } 
class MainArea implements IComponent { } 

// this is a type we want to be passed into INIT as an array 
type InterfaceComponent = (typeof TopBar | typeof StatusBar | typeof MainArea); 

class MyClass { 

    components: {[key:string] : IComponent } = {}; 

    init(params: (InterfaceComponent)[]): void { 
    params.map((component) => { 
     let comp = new component(); 
     this.components[comp.constructor["name"]] = comp; 
    }, this); 
    } 
} 

let x = new MyClass(); 
x.init([TopBar, StatusBar, MainArea]) 

alert(JSON.stringify(x.components)) 

Проверить это here

+0

Это самое элегантное решение, спасибо! Хотя, это означает, что если у меня будет много компонентов, например 100+, мне придется добавить их все к типу 'InterfaceComponent'? –

+0

Ну, трудно сказать без глубокого погружения ... следовать приведенному выше подходу .. нам нужно будет его расширить ... и это не нормально для 100+. Некоторый метод Factory, работающий с переданным неизвестным типом (не таким безопасным типом), был бы более подходящим способом, я бы сказал ... «var instance = Object.create (objectType.prototype); instance.constructor.apply (instance, constructorParameters); ' –

+0

Наследование неверно. Интерфейс InterfaceComponent должен знать все классы, которые его реализуют, конечно, это нехорошо? – davestevens

0

Возможно, вы можете указать тип comp как InterfaceComponent.

var comp: InterfaceComponent = new component(); 
this.components[comp.constructor.name] = comp; 
+1

Последнее, что я хочу сделать с TypeScript, - это присвоение всем типа всем. –

+0

Как насчет его назначения InterfaceComponent – fireydude

0

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

interface InterfaceComponent { 
    name: string; 
} 

class TopBar implements InterfaceComponent { 
    name: string; 
} 

class StatusBar implements InterfaceComponent { 
    name: string; 
} 

class MainArea implements InterfaceComponent { 
    name: string; 
} 

interface InterfaceComponentFactory { 
    create:() => InterfaceComponent; 
} 

function init(params: InterfaceComponentFactory[]): void { 
    params.map(function (component) { 
     let comp = component.create(); 
     this.components[comp.name] = comp; 
    }, this); 
} 

init([{ create:() => new TopBar() }, { create:() => new StatusBar() }, { create:() => new MainArea() }]); 
Смежные вопросы