sylvainpolletvillard / ObjectModel

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

Bug: defaults aren't working #110

Closed kybarg closed 5 years ago

kybarg commented 5 years ago

Code

import { ObjectModel } from 'objectmodel'

const State = ObjectModel({
    string: String,
    number: Number,
})
.defaults({
    string: 'string',
    number: 0,
})

console.log(new State())

Expecred

{
    string: 'string',
    number: 0,
}

Actual result

{}
sylvainpolletvillard commented 5 years ago

Not a bug. In ObjectModel v3, default values are stored in the model prototype, and the default toString method for objects does not show properties from the prototype. But the values are actually right:

import { ObjectModel } from 'objectmodel'

const State = ObjectModel({
    string: String,
    number: Number,
})
.defaults({
    string: 'string',
    number: 0,
})

var s = new State()
console.log(s.string, s.number)

console.log( Object.getPrototypeOf(s) )

This is the intended behaviour, but it causes confusion to many users, that's why I proposed to change this behaviour for v4: https://github.com/sylvainpolletvillard/ObjectModel/issues/93

kybarg commented 5 years ago

@sylvainpolletvillard but can I create new object with prefilled defaults? My use case is I pass object from server side to client, I need at default values to be there.

sylvainpolletvillard commented 5 years ago

The general idea is that defaults should not be part of the data, but part of the model. You don't need to store default values in a database if these values are applied by default when retrieving a missing property. Actually, this is problematic to store default values and send default values to the server since you no longer know what has been applied by default and what has been applied on purpose. So if you store default values, you cannot change the default values if there is existing data, neither can you reapply the default value by deleting a property.

In the end, this is a global misunderstanding of what "by default" means. You are not the only one to come up with this misunderstanding, that's why we will change the behaviour in the next version. But you should note that what you are looking for is not a default value for a property, but a default value to be applied once at object instanciation. Which is a really different concept.

Anyway, you can do this in v3 using a factory function and manually assigning defaults, instead of using the .defaults method.