Nested can-connect models

What is the correct way to create a nested model where the model contains a property which contains a list of object of the same model?

For example

export const Person = can.Map.extend({
    define: {
        mother: {
            Type: Person
        },
        father: {
            Type: Person
        },
        children: {
            Type: Person.List
        }
    }
});

Person.List = can.List.extend({
    Map: Person
});

Obviously that does not work because Product.List has not been defined yet. I tried creating the list first and then attaching the map afterwards, but that doesn’t work either

Person.List = can.List.extend({});

export const Person = can.Map.extend({
    define: {
        mother: {
            Type: Person
        },
        father: {
            Type: Person
        },
        children: {
            Type: PersonList
        }
    }
});

PersonList.Map = Person;
Person.List = PersonList;

The Map property doesn’t seem to take effect after the fact.

The approach I typically use is to modify the Person definition after everything is defined.

Person.prototype.define.children.Type = Person.List;

This can also solve issues with circular dependencies between multiple map definitions.

Alternatively, you can defer the evaluation of the Person.List identifier in your definition like this:

children: {
    type: function(newValue) {
        if (!(newValue instanceof Person.List)) {
            return new Person.List(newValue);
        }
        return newValue;
    }
}

That is essentially what Type does as a convenience, and it works because the function isn’t being evaluated until an instance is created, at which point the Person.List identifier is defined.

Another option that just occurred to me is that you can define the Type property with an ES5 getter:

children: {
    get Type() { return Person.List; }
}