sylvainpolletvillard / ObjectModel

Strong Dynamically Typed Object Modeling for JavaScript
http://objectmodel.js.org
MIT License
467 stars 30 forks source link

Cannot compose sealed ObjectModels #51

Closed dogrover closed 7 years ago

dogrover commented 7 years ago

I'm trying to define a nested object model, where one of the child objects is sealed. For example, this works fine (using v3.0.1):

const Dependency = ObjectModel({
  name: String,
});

const Package = ObjectModel({
  name: String,
  data: {
    description: String,
    hard_dependencies: {
      one: Dependency,
      two: Dependency,
    }
  }
});

const test_item = new Package({
  name: "Test item",
  data: {
    description: "A test item",
    hard_dependencies: {
        one: {
        name: "module 1",
        bad_attr: false,
      },
      two: {
        name: "module 2",
      }
    }
  }
});

But I get an error when I change the Dependency definition to this:

const Dependency = ObjectModel({
  name: String,
}).sealed=true;

The error is:

Uncaught TypeError: expecting data.hard_dependencies.one to be true, got Object { name: "module 1", nope: false } expecting data.hard_dependencies.two to be true, got Object { name: "module 2" } at window.onload (VM180:72)

This seems to be happening because Dependency now gets the value of the assignment from sealed=true, rather than the function that it should be.

I've tried:

var Dependency = ObjectModel({
  name: String,
});
Dependency.sealed=true;

but it has no effect.

Could you provide an example on how to use the sealed property?

sylvainpolletvillard commented 7 years ago

Hello,

In your first example, you are assigning Dependency to true (Dependency = model.sealed = true) The second code is the correct one.

However, currently, the sealed property prevent extensions on future mutations, and not initial assignment. Basically it "seals" the instance after it has been instanciated with initial values. If you try test_item.data.hard_dependencies.one.bad_attr = true afterwards, you will get the intended error message.

I agree this is not intuitive, and I plan to change this and throw errors when undeclared props are passed to sealed model constructors.

sylvainpolletvillard commented 7 years ago

Note that if you want all your models to be sealed, you can set ObjectModel.prototype.sealed = true However, this is not something I would recommend since it prevents model extensions.

dogrover commented 7 years ago

Thanks for the update. And thanks for the module; exactly what I needed! I'll see if I can modify the target code to deal with checking for extra attributes after initial assignment.

sylvainpolletvillard commented 7 years ago

Currently working on it. Stay tuned

sylvainpolletvillard commented 7 years ago

Here we go, v3.1.0 released: