I have a bunch of stores each containing a list of one entity type like
const userStore = EntityStore.create(....)
const supplierStore = EntityStore.create(....)
Some stores can offer additional functionalities, so I wrote
const orderStore = EntityStore
.views(self => ({
allByUserId: branchId => ....)
}))
.create(....)
So far, everything was fine, but now I wanted to create a "store manager" containing a list of all such stores and it failed with a message like
Error: [mobx-state-tree] Error while converting ...
value of type EntityStore: (id: Order)> is not assignable to type:EntityStore
,
expected an instance ofEntityStore
or a snapshot like ... instead
(Note that a snapshot of the provided value is compatible with the targeted type)
The message is clear, my "EntityStore with views" is not of the same type as an "EntityStore". But it's an extension of it, so I wonder if there's a declaration allowing it. Something like List<? extends EntityStore>
in Java?
Or a nice workaround allowing me to add the additional functionality to EntityStore
without changing its type?
No. You can't. Because .views()
(as basically any other dot method) creates a whole new ModelType
object every time you invoke it.
What you could do instead is use a union
type:
types.union(options?: { dispatcher?: (snapshot) => Type, eager?: boolean }, types...)
create a union of multiple types. If the correct type cannot be inferred unambiguously from a snapshot, provide a dispatcher function to determine the type. When eager flag is set to true (default) - the first matching type will be used, if set to false the type check will pass only if exactly 1 type matches.
There's also an example below of how to simulate inheritance by using type composition:
const Square = types
.model(
"Square",
{
width: types.number
}
)
.views(self => ({
surface() {
return self.width * self.width
}
}))
// create a new type, based on Square
const Box = Square
.named("Box")
.views(self => {
// save the base implementation of surface
const superSurface = self.surface
return {
// super contrived override example!
surface() {
return superSurface() * 1
},
volume() {
return self.surface * self.width
}
}
}))
// no inheritance, but, union types and code reuse
const Shape = types.union(Box, Square)
So, no inheritance, but, union types and code reuse.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With