我有一个简单的系统,在该系统中,我可以通过从单独的基类继承它们来生成类,然后将另一个类混合到每个类中。这是我的mixin类:
type Constructor<T = {}> = new (...args: any[]) => T;
/**
* Based on the Mixin idea explained here:
* https://mariusschulz.com/blog/typescript-2-2-mixin-classes
*
* @param base
* @constructor
*/
export function EntityServices<TBase extends Constructor>(base: TBase) {
return class extends base {
private _components = {};
public addComponent(component: Component) {
throw new Error('Not implemented');
}
public removeComponent(component: Component) {
throw new Error('Not implemented');
}
};
}
此mixin用于另一个模块中,以创建如下几类:
class ContainerEntityBase extends Phaser.GameObjects.Container {}
class ImageEntityBase extends Phaser.GameObjects.Image {}
class SpriteEntityBase extends Phaser.GameObjects.Sprite {}
class TextEntityBase extends Phaser.GameObjects.Text {}
export const ContainerEntity = EntityServices(ContainerEntityBase);
export const ImageEntity = EntityServices(ImageEntityBase);
export const SpriteEntity = EntityServices(SpriteEntityBase);
export const TextEntity = EntityServices(TextEntityBase);
// Type definitions have to be exported separately so that they can be used as types elsewhere, not as values
// Same name with values (classes) does not matter since TS stores values and types into separate
// namespaces.
export type ContainerEntity = InstanceType<typeof ContainerEntity>;
export type ImageEntity = InstanceType<typeof ImageEntity>;
export type SpriteEntity = InstanceType<typeof SpriteEntity>;
export type TextEntity = InstanceType<typeof TextEntity>;
export type BlackbirdEntity = ContainerEntity | ImageEntity | SpriteEntity | TextEntity;
如您所见,我已经使用一个额外的联合类型BlackBirdEntity
导出了实际创建的类及其类型。有时,我会使用可能是任何已生成类型的变量,因为在这些情况下,这些实例是通过其常见的混合接口操作的。
接下来,我有以下使用联合类型的简单定义:
import { Component } from '../core/Component';
import { BlackbirdEntity } from '../core/entities';
export interface IEntityDefinition {
name: string;
components: Component[];
type: BlackbirdEntity;
}
我像这样使用它来创建一个实现上述接口的对象:
import { SpriteEntity } from '../core/entities';
import { IEntityDefinition } from './EntityDefinition';
const clickableEntity: IEntityDefinition = {
components: [],
name: 'Clickable',
type: SpriteEntity
};
但是,这使我在IDE上出现以下错误,突出显示了SpriteEntity
:
TS2322: Type '{ new (...args: any[]): EntityServices<typeof SpriteEntityBase>.(Anonymous class); prototype: EntityServices<any>.(Anonymous class); } & typeof SpriteEntityBase' is not assignable to type 'BlackbirdEntity'. Type '{ new (...args: any[]): EntityServices<typeof SpriteEntityBase>.(Anonymous class); prototype: EntityServices<any>.(Anonymous class); } & typeof SpriteEntityBase' is not assignable to type 'EntityServices<typeof TextEntityBase>.(Anonymous class) & TextEntityBase'. Type '{ new (...args: any[]): EntityServices<typeof SpriteEntityBase>.(Anonymous class); prototype: EntityServices<any>.(Anonymous class); } & typeof SpriteEntityBase' is missing the following properties from type 'EntityServices<typeof TextEntityBase>.(Anonymous class)': _components, addComponent, removeComponent
为什么?,以及如何解决此问题?该错误似乎表明SpriteEntity
缺少TextEntity
的父类中实际上存在的属性。那么,即使父母的定义不同,有什么办法告诉编译器这种类型应该没问题吗?
答案 0 :(得分:1)
您的问题是IEntityDefinition
希望其type
属性是BlackbirdEntity
的 instance ,而不是一个{em> constructor 。您可能会感到困惑,因为对于class
,即使they are not the same thing,构造函数 value 通常与实例 type 共享一个名称。
无论如何,您已经有了一个Constructor<T>
类型的别名,所以让我们使用它:
export interface IEntityDefinition {
name: string;
components: Component[];
type: Constructor<BlackbirdEntity>; // you want a constructor, not an instance here
}
这应该使您的clickableEntity
变量初始化可以正确编译。
希望有所帮助;祝你好运!