类型 'N[P]' 不能用于索引类型 'IComponents<N>'
Type 'N[P]' cannot be used to index type 'IComponents<N>'
我试图在打字稿中实现实体组件系统模式。对于要保留实体组件的实体,我有一个 class。我想为这个模式创建一个独立的包,并在我的其他项目中使用它。
这是实体 class,但我有一个错误。
type IComponents<N> = {
[P in keyof N]?: Component<any, N>;
}
// eslint-disable-next-line @typescript-eslint/interface-name-prefix
export interface EntityType<N> {
id: string;
components: IComponents<N>;
addComponent(component: Component<any, N>): void;
removeComponent(componentId: N): void;
print(): void;
}
export default class Entity<N> implements EntityType<N> {
readonly id: string;
components: IComponents<N> = {};
constructor() {
this.id = v4();
}
addComponent(component: Component<any, N>): void {
this.components[component.name] = component;
}
removeComponent(componentName: N): void {
delete this.components[componentName];
}
print(): void {
console.log(JSON.stringify(this, null, 4));
}
}
在方法 addComponents
中我遇到了这个错误
Type 'N' cannot be used to index type 'IComponents<N>'.
这是 Component
class
的签名
export default abstract class Component<P, N> {
readonly id: string;
readonly name: N;
props: P;
protected constructor(props: P, name: N) {
this.props = props;
this.name = name;
this.id = v4();
}
}
有一个项目我使用了这个包:
为组件创建组件、实体和枚举
export enum EComponents {
position,
}
export default (): Entity<EComponents> => {
const player = new Entity<EComponents>();
player.addComponent(new PositionComponent());
return player;
};
获取实体并处理它的系统。在这种方法中,我想从 entity.components
特定组件中获取并处理它
update(entity: Entity): void {
const component: PositionComponent | null = this.getComponent(entity);
if (!component) return;
const { x = 0, y = 0 } = component.props;
const position = { x, y };
if (this.keyboard.isKeyPressed('KeyW')) {
position.y -= 3;
}
if (this.keyboard.isKeyPressed('KeyA')) {
position.x -= 3;
}
if (this.keyboard.isKeyPressed('KeyS')) {
position.y += 3;
}
if (this.keyboard.isKeyPressed('KeyD')) {
position.x += 3;
}
entity.components['Position'].props = position;
}
我写了两种IComponents
和IMappedComponents
。 IComponents
用于从 Component
扩展的组件列表。第二种类型 IMappedComponents
用于 Entity
.
中对象的组件列表
export type IComponents<N extends keyof any> = {
[P in N]?: Component<any, N>;
};
export type IMappedComponents<N extends keyof any, C extends IComponents<N>> = {
[P in N]?: C[P];
};
// eslint-disable-next-line @typescript-eslint/interface-name-prefix
export interface EntityType<N extends keyof any, C extends IComponents<N>> {
id: string;
components: IMappedComponents<N, C>;
addComponent(component: C[N]): void;
removeComponent(componentId: N): void;
print(): void;
}
export default class Entity<N extends keyof any, C extends IComponents<N>> implements EntityType<N, C> {
readonly id: string;
components: IMappedComponents<N, C> = {};
constructor() {
this.id = v4();
}
addComponent(component: C[N]): void {
if (component) {
this.components[component.name] = component;
}
}
removeComponent(componentName: N): void {
delete this.components[componentName];
}
print(): void {
console.log(JSON.stringify(this, null, 4));
}
}
我试图在打字稿中实现实体组件系统模式。对于要保留实体组件的实体,我有一个 class。我想为这个模式创建一个独立的包,并在我的其他项目中使用它。
这是实体 class,但我有一个错误。
type IComponents<N> = {
[P in keyof N]?: Component<any, N>;
}
// eslint-disable-next-line @typescript-eslint/interface-name-prefix
export interface EntityType<N> {
id: string;
components: IComponents<N>;
addComponent(component: Component<any, N>): void;
removeComponent(componentId: N): void;
print(): void;
}
export default class Entity<N> implements EntityType<N> {
readonly id: string;
components: IComponents<N> = {};
constructor() {
this.id = v4();
}
addComponent(component: Component<any, N>): void {
this.components[component.name] = component;
}
removeComponent(componentName: N): void {
delete this.components[componentName];
}
print(): void {
console.log(JSON.stringify(this, null, 4));
}
}
在方法 addComponents
中我遇到了这个错误
Type 'N' cannot be used to index type 'IComponents<N>'.
这是 Component
class
export default abstract class Component<P, N> {
readonly id: string;
readonly name: N;
props: P;
protected constructor(props: P, name: N) {
this.props = props;
this.name = name;
this.id = v4();
}
}
有一个项目我使用了这个包:
为组件创建组件、实体和枚举
export enum EComponents {
position,
}
export default (): Entity<EComponents> => {
const player = new Entity<EComponents>();
player.addComponent(new PositionComponent());
return player;
};
获取实体并处理它的系统。在这种方法中,我想从 entity.components
特定组件中获取并处理它
update(entity: Entity): void {
const component: PositionComponent | null = this.getComponent(entity);
if (!component) return;
const { x = 0, y = 0 } = component.props;
const position = { x, y };
if (this.keyboard.isKeyPressed('KeyW')) {
position.y -= 3;
}
if (this.keyboard.isKeyPressed('KeyA')) {
position.x -= 3;
}
if (this.keyboard.isKeyPressed('KeyS')) {
position.y += 3;
}
if (this.keyboard.isKeyPressed('KeyD')) {
position.x += 3;
}
entity.components['Position'].props = position;
}
我写了两种IComponents
和IMappedComponents
。 IComponents
用于从 Component
扩展的组件列表。第二种类型 IMappedComponents
用于 Entity
.
export type IComponents<N extends keyof any> = {
[P in N]?: Component<any, N>;
};
export type IMappedComponents<N extends keyof any, C extends IComponents<N>> = {
[P in N]?: C[P];
};
// eslint-disable-next-line @typescript-eslint/interface-name-prefix
export interface EntityType<N extends keyof any, C extends IComponents<N>> {
id: string;
components: IMappedComponents<N, C>;
addComponent(component: C[N]): void;
removeComponent(componentId: N): void;
print(): void;
}
export default class Entity<N extends keyof any, C extends IComponents<N>> implements EntityType<N, C> {
readonly id: string;
components: IMappedComponents<N, C> = {};
constructor() {
this.id = v4();
}
addComponent(component: C[N]): void {
if (component) {
this.components[component.name] = component;
}
}
removeComponent(componentName: N): void {
delete this.components[componentName];
}
print(): void {
console.log(JSON.stringify(this, null, 4));
}
}