import type { AbstractModelClass, ModelClass, ModelCreationData, ModelUntransformedCreationData, } from "../modelShared/BaseModelShared" import type { ModelProps, ModelPropsToSetter, ModelPropsToTransformedCreationData, ModelPropsToTransformedData, ModelPropsToUntransformedCreationData, } from "../modelShared/prop" import { sharedInternalModel } from "../modelShared/sharedInternalModel" import type { AnyDataModel, BaseDataModel, BaseDataModelKeys } from "./BaseDataModel" import { assertIsDataModelClass, isDataModelClass } from "./utils" export type _ComposedData = SuperModel extends AnyDataModel ? | (ModelPropsToUntransformedCreationData & ModelUntransformedCreationData) | (ModelPropsToTransformedCreationData & ModelCreationData) : ModelPropsToUntransformedCreationData | ModelPropsToTransformedCreationData export interface _DataModel { new ( data: _ComposedData ): SuperModel & BaseDataModel & Omit, BaseDataModelKeys> & ModelPropsToSetter } /** * Base abstract class for data models that extends another model. * * @template TProps New model properties type. * @template TModel Model type. * @param genFn Function that returns the base model and model properties. * @returns */ export function ExtendedDataModel< TProps extends ModelProps, TModel extends AnyDataModel, A extends [], >( genFn: (...args: A) => { baseModel: AbstractModelClass props: TProps } ): _DataModel /** * Base abstract class for data models that extends another model. * * @template TProps New model properties type. * @template TModel Model type. * @param baseModel Base model type. * @param modelProps Model properties. * @returns */ export function ExtendedDataModel( baseModel: AbstractModelClass, modelProps: TProps ): _DataModel // base export function ExtendedDataModel( ...args: any[] ): _DataModel { let baseModel: AbstractModelClass let modelProps: TProps if (isDataModelClass(args[0])) { baseModel = args[0] modelProps = args[1] } else { const gen = (args[0] as () => { baseModel: ModelClass; props: TProps })() baseModel = gen.baseModel modelProps = gen.props } assertIsDataModelClass(baseModel, "baseModel") return internalDataModel(modelProps, baseModel as any) } /** * Base abstract class for data models. * * Never override the constructor, use `onLazyInit` or `onLazyAttachedToRootStore` instead. * * @template TProps Model properties type. * @param fnModelProps Function that generates model properties. */ export function DataModel( fnModelProps: (...args: A) => TProps ): _DataModel /** * Base abstract class for data models. * * Never override the constructor, use `onLazyInit` or `onLazyAttachedToRootStore` instead. * * @template TProps Model properties type. * @param modelProps Model properties. */ export function DataModel( modelProps: TProps ): _DataModel // base export function DataModel( fnModelPropsOrModelProps: (() => TProps) | TProps ): _DataModel { const modelProps = typeof fnModelPropsOrModelProps === "function" ? fnModelPropsOrModelProps() : fnModelPropsOrModelProps return internalDataModel(modelProps, undefined) } function internalDataModel( modelProps: TProps, baseModel: ModelClass | undefined ): _DataModel { return sharedInternalModel({ modelProps, baseModel, type: "data", valueType: false, fromSnapshotProcessor: undefined, toSnapshotProcessor: undefined, }) }