import { Prettify, StoreSpec, StateOf, ActionsOf, SelectorContext, Factory } from '../types'; export type Mixin = (context: TContext) => TResult; /** * Map of named mixins where each key maps to a mixin function. * * @example * ```ts * const mixins: MixinMap = { * name: (ctx) => ctx.get(userStore)[0].name, * count: (ctx) => ctx.get(counterStore)[0].count, * }; * ``` */ export type MixinMap = Record>; /** * A mixin item for merge: either a direct mixin function or a record of named mixins. * - Direct mixin: `(ctx) => ({ name, age })` → spreads result into final object * - Named mixin: `{ userName: (ctx) => state.name }` → maps key to mixin result */ export type MergeMixinItem = Mixin | MixinMap; /** * Array of mixin items for composing multiple mixins. * * @example * ```ts * const mixins: MergeMixin = [ * selectUser, // Direct mixin - spreads result * { count: selectCount }, // Named mixin - maps key * ]; * ``` */ export type MergeMixin = readonly MergeMixinItem[]; /** * Infer result type from a record of named mixins. * `{ value: (ctx) => 123, fn: (ctx) => () => {} }` → `{ value: number, fn: () => void }` */ export type InferMixinRecord, C> = T extends MixinMap ? { [K in keyof T]: T[K] extends Mixin ? R : never; } : never; /** * Infer result from a single mixin item. */ export type InferMixinItem = T extends Mixin ? R : T extends MixinMap ? InferMixinRecord : never; /** * Recursively infer and merge types from MergeMixin array. */ export type InferMergeMixin, C> = T extends readonly [ infer First, ...infer Rest extends MergeMixin ] ? InferMixinItem & InferMergeMixin : unknown; /** * Final merged result type with prettified output. */ export type MergeMixinResult, C> = Prettify>; /** * Result type for MixinMap - maps keys to their mixin results. */ export type MixinMapResult, C> = Prettify>; /** * Extract context type from a record of mixin functions. */ type ExtractMixinContext = T extends Record> ? C : T extends Mixin ? C : never; /** * Extract context type from an array of mixin items. */ type ExtractArrayMixinContext = T extends readonly [infer First, ...infer Rest] ? ExtractMixinContext | ExtractArrayMixinContext : never; /** * Remove "Mixin" suffix from a string type. * `"userMixin"` → `"user"` * `"selectCount"` → `"selectCount"` (no change) */ type StripMixinSuffix = S extends `${infer Prefix}Mixin` ? Prefix : S; /** * Strip Mixin suffix from record keys (readonly). */ type StripMixinSuffixFromRecord> = { readonly [K in keyof T as K extends string ? StripMixinSuffix : K]: T[K] extends Mixin ? R : never; }; /** * Infer result from a single mixin array item with Mixin suffix stripping. * Direct mixin results are made readonly. */ type InferMixinArrayItem = T extends Mixin ? Readonly : T extends Record ? StripMixinSuffixFromRecord : never; /** * Recursively infer and merge types from mixin array. */ type InferMixinArray = T extends readonly [ infer First, ...infer Rest ] ? InferMixinArrayItem & InferMixinArray : unknown; /** * Proxy type for accessing store state properties and actions as mixins. * State properties return mixins that access state values. * Actions return mixins that access action functions. */ export type MixinProxy> = { readonly [K in keyof StateOf]: Mixin[K], SelectorContext>; } & { readonly [K in keyof ActionsOf]: Mixin[K], SelectorContext>; } & { /** * Select multiple properties/actions as a composed mixin. * * @example * ```ts * // Array syntax - use property names as keys * const proxy = mixins(userStore); * const userMixin = proxy.select(["name", "age", "setName"]); * // Returns: (ctx) => ({ name: string, age: number, setName: function }) * * // Object syntax - map to custom keys * const userMixin = proxy.select({ userName: "name", userAge: "age", updateName: "setName" }); * // Returns: (ctx) => ({ userName: string, userAge: number, updateName: function }) * ``` */ select | keyof ActionsOf)[]>(keys: TKeys): Mixin<{ readonly [K in TKeys[number]]: K extends keyof StateOf ? StateOf[K] : K extends keyof ActionsOf ? ActionsOf[K] : never; }, SelectorContext>; select | keyof ActionsOf>>(map: TMap): Mixin<{ readonly [K in keyof TMap]: TMap[K] extends keyof StateOf ? StateOf[TMap[K]] : TMap[K] extends keyof ActionsOf ? ActionsOf[TMap[K]] : never; }, SelectorContext>; }; /** * Proxy type for accessing service factory properties as mixins. * Each property of the service instance becomes a mixin. */ export type ServiceMixinProxy = { readonly [K in keyof T]: Mixin; }; /** * Compose multiple mixins into a single mixin function. * Accepts any mixin type (Selector or Store context). * Automatically removes "Mixin" suffix from keys. * * @example * ```ts * // Object syntax - named mixins * const composed = mixins({ userMixin, countMixin }); * // Returns: (ctx) => { user: User, count: number } * * // Array syntax - merge mixins * const merged = mixins([selectUserMixin, { countMixin }]); * // Returns: (ctx) => { name: string, age: number, count: number } * * // Store spec syntax - proxy for state/actions * const proxy = mixins(userStore); * const { name, doSomething } = useStore(mixins({ * name: proxy.name, * doSomething: proxy.doSomething, * })); * * // Factory syntax - proxy for service properties * const dbService = (resolver: Resolver) => ({ * users: { getAll: () => [] }, * posts: { getAll: () => [] }, * }); * const serviceProxy = mixins(dbService); * const { users } = useStore(mixins({ * users: serviceProxy.users, * })); * ``` */ export declare function mixins>(spec: TSpec): MixinProxy; export declare function mixins(factory: Factory): ServiceMixinProxy; export declare function mixins | Record)[]>(mixinArray: T): (context: ExtractArrayMixinContext) => Prettify>; export declare function mixins>(mixinMap: T): (context: ExtractMixinContext) => Prettify>; export {}; //# sourceMappingURL=mixins.d.ts.map