/**
 * A mapping of variant names to their payload factory functions.
 *
 * Each key defines a variant constructor that returns an object payload.
 * Used as the input to `matchable()`.
 */
type VariantMap = Record<string, (...args: any[]) => Record<string, any>>;
/**
 * Infers the union type from a `VariantMap`.
 *
 * Wraps each payload in a `{ tag: ... }` object for pattern matching.
 */
type InferUnion<M extends VariantMap> = {
    [K in keyof M]: M[K] extends (...args: any[]) => infer R ? R & {
        tag: K;
    } : never;
}[keyof M & string];
/**
 * A handler map for `match()`, where each tag maps to a function.
 *
 * Can optionally include a `default` fallback.
 */
type MatchHandlers<U extends {
    tag: string;
}, R> = {
    [K in Exclude<U["tag"], "default">]?: (value: Extract<U, {
        tag: K;
    }>) => R;
} & {
    default?: (value: U) => R;
};
/**
 * A more flexible match handler shape that allows partial matching
 * as long as a `default` handler is provided.
 */
type MatchWithDefault<U extends {
    tag: string;
}, R> = MatchHandlers<U, R> | (Partial<Omit<MatchHandlers<U, R>, "default">> & {
    default: (value: U) => R;
});
/**
 * Extracts the union type from a matchable instance.
 *
 * @example
 * const Result = matchable({
 *   Ok: (value: number) => ({ value }),
 *   Err: (message: string) => ({ message }),
 * });
 *
 * type ResultType = MatchableOf<typeof Result>;
 * // => { tag: "Ok"; value: number } | { tag: "Err"; message: string }
 */
type MatchableOf<T> = T extends {
    match: (value: infer U, ...args: any[]) => any;
} ? U : never;
/**
 * Extracts a specific variant from a matchable union.
 *
 * @example
 * type OkVariant = VariantOf<typeof Result, "Ok">;
 * // => { tag: "Ok"; value: number }
 */
type VariantOf<T, Tag extends string> = Extract<MatchableOf<T>, {
    tag: Tag;
}>;
/**
 * Extracts the union of all possible `tag` values from a matchable instance.
 *
 * @example
 * const Result = matchable({
 *   Ok: (value: number) => ({ value }),
 *   Err: (error: string) => ({ error }),
 * });
 *
 * type ResultTags = TagsOf<typeof Result>;
 * // => "Ok" | "Err"
 */
type TagsOf<T> = MatchableOf<T> extends {
    tag: infer Tag;
} ? Tag : never;

/**
 * Merges multiple match handlers into a single handler map,
 * preserving the shape expected by `.match()`.
 *
 * Useful when multiple tags share logic and should map
 * to the same function. You can still provide a `default`
 * fallback for any unhandled tags.
 *
 * @param matchable - A matchable instance with `_tags` and `match()`
 *
 * @param handlers - A partial set of handlers for specific tags, plus optional `default`
 *
 * @returns A `MatchWithDefault` handler map compatible with `match()`
 *
 * @example
 * const handlers = group(Result, {
 *   Ok: handleSuccess,
 *   Cached: handleSuccess,
 *   Err: handleError,
 * });
 *
 * const message = Result.match(value, handlers);
 */
declare function group<T extends {
    match: (value: any, handlers: any) => any;
}, U extends MatchableOf<T>, R>(matchable: T & {
    _tags: readonly string[];
}, handlers: {
    [K in Exclude<U["tag"], "default">]?: (value: Extract<U, {
        tag: K;
    }>) => R;
} & {
    default?: (value: U) => R;
}): MatchWithDefault<U, R>;

/**
 * Validates if a value matches one of the known tags.
 *
 * Useful for safely checking data loaded from storage, APIs, etc.
 *
 * @param matchable - The matchable instance with `_tags`
 *
 * @param value - The value to check
 *
 * @returns `true` if the value has a valid tag
 */
declare function isValid<T extends {
    _tags: readonly string[];
}>(matchable: T, value: unknown): value is {
    tag: T["_tags"][number];
};

declare const MATCHABLE_INTERNAL_ID: unique symbol;

declare function serialize<M extends VariantMap>(value: InferUnion<M>): string;

/**
 * Creates a tagged union and a type-safe matcher.
 *
 * Each key in `variants` becomes a constructor function that returns
 * an object with a `tag` and a payload. Use `match()` to handle variants
 * exhaustively, or include a `default` handler for partial matching.
 *
 * @param variants - A map of variant names to factory functions.
 *
 * @returns An object with:
 * - constructors for each variant
 * - a `match()` function for safe pattern matching
 * - a `is` object with type guards
 * - `_tags` listing supported tags
 *
 * @example
 * const Result = matchable({
 *   Ok: (value: number) => ({ value }),
 *   Err: (message: string) => ({ message }),
 * });
 *
 * const result = Result.Ok(42);
 * const msg = Result.match(result, {
 *   Ok: ({ value }) => `✅ ${value}`,
 *   Err: ({ message }) => `❌ ${message}`,
 * });
 */
declare function matchable<const M extends VariantMap>(variants: M): { [K in keyof M & string]: (...args: Parameters<M[K]>) => ReturnType<M[K]> & {
    __matchable_id__: typeof MATCHABLE_INTERNAL_ID;
    tag: K;
}; } & {
    _tags: (keyof M & string)[];
    deserialize: (json: string) => {
        tag: keyof M & string;
    };
    is: { [K_1 in keyof M & string]: (value: unknown) => value is {
        tag: K_1;
    }; } & {
        Valid: (value: unknown) => value is {
            tag: keyof M & string;
        };
    };
    match: <R>(value: InferUnion<M> & {
        __matchable_id__?: symbol;
    }, handlers: MatchWithDefault<InferUnion<M> & {
        __matchable_id__?: symbol;
    }, R>) => R;
    serialize: typeof serialize;
};

export { type MatchableOf, type TagsOf, type VariantOf, group, isValid, matchable };
