import { AbstractModelClass, ModelClass, propsTypeSymbol } from '../modelShared/BaseModelShared'; import { ModelProps, ModelPropsToTransformedData } from '../modelShared/prop'; import { AnyModel, BaseModelKeys } from './BaseModel'; type ReqObj = [unknown] extends [Req] ? unknown : Req extends object ? Req : never; declare const reqMarkerBrand: unique symbol; /** * Typed requirement marker created by `req()`. * Pass it as the second argument to `defineModelMixin` to declare that the base model must already * contain the `Req` shape before the mixin is applied. */ export type ReqMarker = { readonly [reqMarkerBrand]: Req; }; /** * Creates a typed requirement marker for `defineModelMixin`. * * @template Req Shape that must exist on the base model instance. * * @example * const producerMixin = defineModelMixin( * { produced: tProp(types.number, 0) }, * req<{ quantity: number }>() * ) */ export declare function req(): ReqMarker; /** * Mixin function type for model classes. * * @template Added Shape added by the mixin. * @template Req Shape that must exist in the input model instance. * @template ExtraProps ModelProps to merge into the class's propsTypeSymbol marker. When using * `defineModelMixin`, this is always set to the real `ModelProps` object so that `ModelData` / * `ModelCreationData` resolve to the exact prop types. */ export type ModelMixin = >>(base: B) => ModelClass & Added & { [propsTypeSymbol]: ExtraProps; }>; type MixinAdded> = M extends ModelMixin ? Added : never; type MixinReq> = M extends ModelMixin ? ReqObj : never; type MixinExtraProps> = M extends ModelMixin ? P : never; type ApplyMixin, M extends ModelMixin> = ModelClass & MixinAdded & { [propsTypeSymbol]: MixinExtraProps; }>; type ApplyMixins, M extends readonly ModelMixin[]> = M extends readonly [infer First, ...infer Rest] ? First extends ModelMixin ? ApplyMixins, Extract[]>> : never : B; /** * Computes the resulting model class after applying a mixin tuple to a base model class. */ export type ComposedModelClass, M extends readonly ModelMixin[]> = ApplyMixins; /** * Computes the resulting model instance type after applying a mixin tuple to a base model class. */ export type ComposedModelInstance, M extends readonly ModelMixin[]> = InstanceType>; type ValidateMixins, M extends readonly ModelMixin[]> = M extends readonly [infer First, ...infer Rest] ? First extends ModelMixin ? InstanceType extends AnyModel & MixinReq ? readonly [ First, ...ValidateMixins, Extract[]>> ] : never : never : readonly []; /** * Defines a model mixin from a `ModelProps` object. * * `ModelData` / `ModelCreationData` on the composed class resolve to the exact prop types. * * @template MP Model properties type (inferred from `props`). * @param props Model properties object. * * @example * const countableMixin = defineModelMixin({ quantity: tProp(types.number, 0) }) */ export declare function defineModelMixin(props: MP): ModelMixin, unknown, MP>; /** * Defines a model mixin from a `ModelProps` object, with a requirement on the base model. * * Pass `req()` as the second argument to declare that the base model must already contain the * `Req` shape before the mixin is applied. * * @template Req Shape that must exist on the base model instance (specified via `req()`). * @template MP Model properties type (inferred from `props`). * @param props Model properties object. * @param requirement Requirement marker created by `req()`. * * @example * const producerMixin = defineModelMixin( * { produced: tProp(types.number, 0) }, * req<{ quantity: number }>() * ) */ export declare function defineModelMixin(props: MP, requirement: ReqMarker): ModelMixin, Req, MP>; /** * Defines a model mixin from a `ModelProps` object and a builder that can add actions and other * methods. * * The props are applied via `ExtendedModel` first; the resulting pre-extended class is passed to * the builder so you can simply `extend Base` without calling `ExtendedModel` yourself. * `ModelData` / `ModelCreationData` resolve to the exact prop types from `MP`. * * @template MP Model properties type (inferred from `props`). * @template C Built class type (inferred from `build` return type). * @param props Model properties object. * @param build Builder receiving the pre-extended base class. * * @example * const countableMixin = defineModelMixin( * { quantity: tProp(types.number, 0) }, * (Base) => class Countable extends Base { * increment() { this.quantity++ } * } * ) */ export declare function defineModelMixin>>(props: MP, build: (base: AbstractModelClass>) => C): ModelMixin, BaseModelKeys>, unknown, MP>; /** * Defines a model mixin from a `ModelProps` object and a builder, with a requirement on the base * model. * * Pass `req()` as the second argument to declare that the base model must already contain the * `Req` shape. The `Base` class received by the builder includes both the prop types and `Req`. * * @template Req Shape that must exist on the base model instance (specified via `req()`). * @template MP Model properties type (inferred from `props`). * @template C Built class type (inferred from `build` return type). * @param props Model properties object. * @param requirement Requirement marker created by `req()`. * @param build Builder receiving the pre-extended base class (typed with both props and `Req`). * * @example * const producerMixin = defineModelMixin( * { produced: tProp(types.number, 0) }, * req<{ quantity: number }>(), * (Base) => class Producer extends Base { * produceTotal() { return this.produced + this.quantity } * } * ) */ export declare function defineModelMixin>>(props: MP, requirement: ReqMarker, build: (base: AbstractModelClass & Req>) => C): ModelMixin, BaseModelKeys>, Req, MP>; declare const MixinEmptyBase_base: import('./Model')._Model; declare class MixinEmptyBase extends MixinEmptyBase_base { } /** * Composes several model mixins without an explicit base model class. * * An implicit empty base (`Model({})`) is used. Useful for bundling mixins to reuse across * multiple concrete classes: * * ```ts * const ProductBase = composeMixins(countableMixin, producerMixin) * * @model("myApp/Product") * class Product extends ExtendedModel(ProductBase, {}) {} * ``` * * @template M Mixin tuple type. * @param mixins Mixins to apply. * @returns A model class with all mixin additions applied over an empty base. */ export declare function composeMixins[]>(...mixins: M & ValidateMixins): ComposedModelClass; /** * Composes several model mixins over a base model class. * * @template B Base model class. * @template M Mixin tuple type. * @param base Base model class. * @param mixins Mixins to apply. * @returns A model class with all mixin additions applied. */ export declare function composeMixins, M extends readonly ModelMixin[]>(base: B, ...mixins: M & ValidateMixins): ComposedModelClass; export {};