ecsyjs / ecsy

Entity Component System for javascript
https://ecsyjs.github.io/ecsy/
MIT License
1.11k stars 115 forks source link

TypeScript: Generic type 'Component<C>' requires 1 type argument(s) #282

Closed jerrygreen closed 3 years ago

jerrygreen commented 3 years ago

I have this simplest ECSY component written in TypeScript:

import { Component, Types } from 'ecsy'

const schema = {
  primitive: { type: Types.String, default: 'box' },
}

class Shape extends Component {}

Shape.schema = schema

export default Shape

And I have further error:

Generic type 'Component' requires 1 type argument(s).

image

I initially thought it's component's schema, and tried doing this:

import { Component, Types } from 'ecsy'

const schema = {
  primitive: { type: Types.String, default: 'box' },
}

class Shape extends Component<typeof schema> {}

Shape.schema = schema

export default Shape

But later on upon using this, I faced further error:

Property 'primitive' does not exist on type 'Readonly<Component>'

image

From component definition I don't quite understand: what is this? Here's its definition:

export class Component<C> {
  static schema: ComponentSchema;
  static isComponent: true;
  constructor(props?: Partial<Omit<C, keyof Component<any>>> | false);
  copy(source: this): this;
  clone(): this;
  reset(): void;
  dispose(): void;
}

What is this C? And how do I deal with this Property 'primitive' does not exist on type 'Readonly<Component<any>>' error?

marlonicus commented 3 years ago

Just in case you're still wondering, this approach to writing components should solve the problem:

import { Component, Types } from "ecsy"

class MyComponent extends Component<MyComponent> {
  foo!: boolean
  bar?: boolean // optional property

  static schema = {
    foo: { type: Types.Boolean, default: false },
    bar: { type: Types.Boolean }
  }
}
jerrygreen commented 3 years ago

Thx for sharing (I guess I may close this now), though actually I decided to write my own ECS implementation, and ended up with components being simple js objects, while the rest classes like Entity, System, World, - they're all replaced with different implementation having similar API. I wrote a couple posts about it here:

I honestly don't see any reasons why components should be classes, when it's basically data and doesn't (shouldn't) have any logic implementation. In my second article I feature how GPU usage / CPU usage / FPS, - all improved due to all my changes. Schemas and queries gone down to attribute access, and overall types are more straightforward.