ECS System in Javascript I'm trying to get a better feel for how an entity-component-system system works. I'm most comfortable in JavaScript, so that's what I wrote it in. I'm mostly looking for ways my code violates ECS principles, but am also looking for ways to make my code more idiomatic.

class Component {
    get type() { return this.constructor.name; }

    constructor(data) {
        this.data = data;
    }
}

class Entity {
    get type() { return this.constructor.name; }

    constructor(id) {
        this.id = id;
        this.components = [];
    }

    get(type) { return this.components.find(c =&gt; c.type === type); }

    assign(component) {
        const included = this.get(component.type);
        if (included === undefined) this.components.push(component);
        else this.components[this.components.indexOf(included)] = component;
    }
}

class System {
    get type() { return this.constructor.name; }

    constructor(types, callback) {
        this.types = types;
        this.callback = callback;
    }

    run(entities) {
        entities.forEach(e =&gt; 
            this.types.every(t =&gt; e.get(t) !== undefined) &amp;&amp;
            this.callback(e)
        );
    }
}


Also, here's a basic example of how the system gets extended.

class ErrorComponent extends Component {
    constructor(error) {
        super(error);
    }
}

class ErrorSystem extends System {
    constructor() {
        super(
            ["ErrorComponent"],
            e =&gt; console.error(e.get("ErrorComponent").data)
        );
    }
}
const testComponent = new ErrorComponent("test");
const testComponent2 = new ErrorComponent("test2");

const testEntity = new Entity("test");
testEntity.assign(testComponent);
testEntity.assign(testComponent2);

const entities = [testEntity];
const testSystem = new ErrorSystem();
testSystem.run(entities);


One other thing that I feel like I don't understand about ECS is why I should extend Component and System, but not Entity. It feels asymmetrical. For example, could I say 

class ErrorEntity extends Entity {
    constructor(id, error) {
        super(id);
        this.assign(new ErrorComponent(error));
    }
}


?
Or does this violate some principle of ECS?
I didn't like the strings in the ErrorSystem call, so I factored them out. Comments and additional answers are still welcome.

class Component {
    constructor(data) {
        this.data = data;
    }
} 

class Entity {
    constructor(id) {
        this.id = id;
        this.components = [];
    }

    type(component) {
        return component.prototype === undefined?
            component.constructor.name:
            component.prototype.constructor.name;
    }

    get(component) { return this.components.find(c =&gt; this.type(c) === this.type(component)); }

    set(component) {
        const included = this.get(component);
        if (included === undefined) this.components.push(component);
        else this.components[this.components.indexOf(included)] = component;
    }
}

class System {
    constructor(components, callback) {
        this.components = components;
        this.callback = callback;
    }

    run(entities) {
        entities.forEach(e =&gt; 
            this.components.every(c =&gt; e.get(c) !== undefined) &amp;&amp;
            this.callback(e)
        );
    }
}


class ErrorComponent extends Component {
    constructor(error) {
        super(error);
    }
}

class ErrorSystem extends System {
    constructor() {
        super(
            [ErrorComponent],
            e =&gt; console.error(e.get(ErrorComponent).data)
        );
    }
}

const testComponent = new ErrorComponent("test");

const testEntity = new Entity("test");
testEntity.set(testComponent);

const entities = [testEntity];
const testSystem = new ErrorSystem();
testSystem.run(entities);