You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于静态成员生成类型,避免重复定义ECSY系统的queries?

解决ECSY中System类queries静态与实例类型重复定义的问题

你可以通过TypeScript的typeof操作符结合映射类型,完全复用静态queries的结构来推导实例queries的类型,不需要手动重复每个属性定义。

基础实现代码

import { System, Entity } from 'ecsy';

// 假设你的组件类定义如下
class Object3D {}
class Interactable {}
class Camera {}

export class PointerSystem extends System {
    // 静态查询定义,加上as const锁定键名的字面量类型
    static queries = {
        interactable: {
            components: [Object3D, Interactable]
        },
        camera: {
            components: [Camera]
        },
    } as const;

    // 通过映射类型自动推导实例queries的结构
    queries: {
        [K in keyof typeof PointerSystem.queries]: {
            results: Entity[]
        }
    };

    execute() {
        // 直接使用推导后的类型,无需担心属性不存在或类型不匹配
        this.queries.interactable.results.forEach(entity => {
            const obj = entity.getComponent(Object3D);
            const interactable = entity.getComponent(Interactable);
            // 处理逻辑
        });

        this.queries.camera.results.forEach(cameraEntity => {
            const camera = cameraEntity.getComponent(Camera);
            // 处理逻辑
        });
    }
}

优化:让results类型更精确

如果希望results里的实体类型能体现出它包含哪些组件,可以定义通用类型进一步推导:

// 定义通用类型,关联查询的组件与实体类型
type QueryEntities<T extends { components: any[] }> = Array<
    Entity & {
        getComponent<C extends T['components'][number]>(comp: new () => C): C;
    }
>;

export class PointerSystem extends System {
    static queries = {
        interactable: {
            components: [Object3D, Interactable]
        },
        camera: {
            components: [Camera]
        },
    } as const;

    queries: {
        [K in keyof typeof PointerSystem.queries]: {
            results: QueryEntities<typeof PointerSystem.queries[K]>
        }
    };

    execute() {
        // 此时调用getComponent时,TypeScript会自动提示可用的组件类型
        this.queries.interactable.results.forEach(entity => {
            // 编辑器会自动补全Object3D和Interactable
            const obj = entity.getComponent(Object3D);
        });
    }
}

核心原理

  1. as const:锁定静态queries的键名和组件数组的字面量类型,避免TypeScript将键名拓宽为string类型,保证映射类型能准确遍历所有查询键。
  2. 映射类型[K in keyof typeof PointerSystem.queries]:遍历静态queries的所有属性名,为每个属性生成对应的{ results: ... }结构,完全复用静态定义的结构,无需手动重复。

内容的提问来源于stack exchange,提问作者munHunger

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 10:17:08