在 mobx 状态树中扩展模型

maa*_*nus 9 mobx-state-tree

我有一堆商店,每个商店都包含一个实体类型的列表,例如

const userStore = EntityStore.create(....)

const supplierStore = EntityStore.create(....)
Run Code Online (Sandbox Code Playgroud)

有些商店可以提供额外的功能,所以我写了

const orderStore = EntityStore
.views(self => ({
    allByUserId: branchId => ....)
}))
.create(....)
Run Code Online (Sandbox Code Playgroud)

到目前为止,一切都很好,但现在我想创建一个“商店经理”,其中包含所有此类商店的列表,但失败并显示如下消息

错误:[mobx-state-tree] 转换 ...
EntityStore 类型的值时出错:(id: Order)> 不可分配给 type: EntityStore
应为 ... 的实例EntityStore或类似的快照
(请注意,快照提供的值与目标类型兼容)

消息很明确,我的“EntityStore with views”与“EntityStore”的类型不同。但它是它的扩展,所以我想知道是否有声明允许它。像List<? extends EntityStore>Java中的东西?

或者一个很好的解决方法,允许我在EntityStore不改变其类型的情况下添加附加功能?

jay*_*rjo 9

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)
Run Code Online (Sandbox Code Playgroud)

So, no inheritance, but, union types and code reuse.