Skip to content

Top-Level App Type Resolution Issue in Ecsify #107

@bennobuilder

Description

@bennobuilder

TypeScript fails to resolve the app type at module level, resulting in never type for top-level app instances.

Minimal Example

// This works fine inside test function scope
it('should work', () => {
  const app = createApp({
    plugins: [createDefaultPlugin(), createGamePlugin()] as const,
    systemSets: ['First', 'Update', 'Last']
  });
  app.update(); // ✅ Works fine
});

// But fails at module level
const app = createApp({
  plugins: [createDefaultPlugin(), createGamePlugin()] as const,
  systemSets: ['First', 'Update', 'Last']
});
app.update(); // ❌ Error: Property 'update' does not exist on type 'never'

Root Cause

The issue (probably) stems from a circular type dependency in the plugin system. Here's the exact dependency chain:

TPlugin 
  -> setup: (app: TApp<GAppContext>) 
    -> TApp 
      -> TAppContext 
        -> TMergePlugins 
          -> TAnyPlugin 
            -> TPlugin

The circular dependency occurs because:

  1. Plugin's setup function needs TApp<GAppContext> type
  2. TApp depends on TAppContext for extensions
  3. TAppContext uses TMergePlugins to combine plugin shapes
  4. TMergePlugins works with TAnyPlugin
  5. TAnyPlugin is based on TPlugin, completing the circle

TypeScript can resolve this in function scope where it has complete type context, but fails at module level during initial pass.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions