我有一个应用程序通过运行方法.init(params)
进行初始化,如下所示:
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);
问题在于,由于这些不是实例,因此TypeScript不知道其类型并引发错误:
错误TS2345:类型的参数'(typeof TopBar | typeof StatusBar | typeof MainArea)[]'不能分配给类型的参数 'IComponent的[]'。
如何修复代码以便我可以将实现某个接口的类数组传递给方法?
答案 0 :(得分:3)
有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
答案 1 :(得分:0)
也许您可以将comp
的类型指定为InterfaceComponent
。
var comp: InterfaceComponent = new component();
this.components[comp.constructor.name] = comp;
答案 2 :(得分: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() }]);
答案 3 :(得分:0)
Typescript支持类类型泛型(TypeScript Docs)。他们的例子是:
function create<T>(c: {new(): T; }): T {
return new c();
}
哪个说“将{传给我的create
方法的类在构造时将返回我想要的类型T”。此签名将阻止您尝试传递非T类型的任何类类型。
这很接近我们想要的,我们只需要对其进行调整,使其成为您的IComponent
的一系列商品即可。
public init(components: {new(): IComponent;}[]): void {
// at this point our `components` variable is a collection of
// classes that implement IComponent
// for example, we can just new up the first one;
var firstComponent = new components[0]();
}, this);
有了方法签名,我们现在可以像使用它一样
app.init([TopBar, StatusBar, MainArea]);
我们在其中传递实现IComponent
的类型数组
答案 4 :(得分:0)
即使这是一个古老的问题:这是您的操作方式:
interface IComponent { something(): void; }
class TopBar implements IComponent { something() { console.log('in TopBar'); }}
class StatusBar implements IComponent { something() { console.log('in StatusBar'); }}
class MainArea implements IComponent { something() { console.log('in MainArea'); }}
interface ComponentClass {
new(): IComponent;
}
const components: { [name: string]: IComponent } = {};
function init(params: ComponentClass[]) {
params.map((component) => {
let comp = new component();
components[component.name] = comp;
});
}
init([TopBar, StatusBar, MainArea]);
for (const c in components) {
console.log('Component: ' + c);
components[c].something();
}
答案 5 :(得分:0)
对于这种情况,我发现了两种创建类型的不同方法:
// Interface style:
export default interface IConstructor<T> extends Function {
new (...args: any[]): T;
}
// Union Type style:
export type ConstructorUnion<T> = new(...args : any[]) => T;
这就是IConstructor
类型的外观:
interface IComponent { }
class TopBar implements IComponent { }
class StatusBar implements IComponent { }
class MainArea { }
class App {
public components: { [key: string]: IComponent } = {};
public init(params: IConstructor<IComponent>[]): void {
params.forEach((Component: IConstructor<IComponent>) => {
const comp: IComponent = new Component();
this.components[comp.constructor.name] = comp;
});
}
}
const app = new App();
app.init([TopBar, StatusBar, MainArea]);
console.clear();
console.log(app);
这是代码: https://stackblitz.com/edit/how-to-type-an-array-with-classes-in-typescript?file=index.ts