Расширение модели в дереве состояний mobx

У меня есть куча магазинов, каждый из которых содержит список одного типа объекта, как

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

const supplierStore = EntityStore.create(....)

Некоторые магазины могут предложить дополнительные функциональные возможности, поэтому я написал

const orderStore = EntityStore
.views(self => ({
    allByUserId: branchId => ....)
}))
.create(....)

До сих пор все было хорошо, но теперь я хотел создать "менеджер магазина", содержащий список всех таких магазинов, и это не удалось с сообщением типа

Ошибка: [mobx-state-tree] Ошибка при преобразовании...
значение типа EntityStore: (id: Order)> не присваивается типу: EntityStore,
ожидаемый случай EntityStore или снимок, как... вместо
(Обратите внимание, что снимок предоставленного значения совместим с целевым типом)

Сообщение ясно, мой "EntityStore с представлениями" не того типа, что и "EntityStore". Но это расширение, поэтому мне интересно, есть ли декларация, разрешающая это. Что-то вроде List<? extends EntityStore> в Java?

Или хороший обходной путь, позволяющий мне добавить дополнительную функциональность EntityStore без изменения его типа?

1 ответ

Решение

Нет, ты не можешь Так как .views() (как и любой другой метод точек) создает совершенно новый ModelType возражать каждый раз, когда вы вызываете его.

Вместо этого вы можете использовать union тип:

  • types.union(options?: { dispatcher?: (snapshot) => Type, eager?: boolean }, types...) создать объединение нескольких типов. Если правильный тип не может быть однозначно выведен из снимка, предоставьте функцию диспетчера для определения типа. Когда eager flag установлен в true (по умолчанию) - будет использован первый соответствующий тип, если установлен в false, проверка типа будет проходить, только если точно соответствует 1 типу.

Ниже также приведен пример того, как имитировать наследование с использованием композиции типов:

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)

Таким образом, не наследование, а объединение типов и повторное использование кода.

Другие вопросы по тегам