/**
 * Utility type to extract the variant of a discriminated union.
 *
 * @template T - The union type.
 * @template K - The discriminator key.
 * @template V - The discriminator value.
 */
type VariantOf<T, K extends keyof T, V> = T extends Record<K, V> ? T : never;
/**
 * Represents a handler for a case in a switch-case structure.
 *
 * @template T - The type of the value being matched.
 * @template R - The return type of the handler function.
 * @property {T} match - A value or a function to match against the input.
 * @property {(val: T) => R} handler - A function that processes the matched value and returns a result.
 */
type CaseHandler<T, R> = {
    match: T;
    handler: (val: T) => R;
} | {
    match: (val: T) => boolean;
    handler: (val: T) => R;
};
/**
 * Interface for building a switch-case structure with fluent API.
 *
 * @template T - The type of the value being matched.
 * @template R - The return type of the handler functions.
 * @template Remaining - The remaining keys that can be matched.
 */
interface SwitchCaseBuilder<T, R, Remaining extends string | number | symbol = never> {
    /**
     * Adds a case to the switch-case structure.
     *
     * @template K - The type of the key being matched.
     * @param {K} match - A value to match or a function to evaluate the match.
     * @param {R | (() => R)} handler - A result or a function that returns a result for the matched case.
     * @returns {SwitchCaseBuilder<T, R, Exclude<Remaining, K>>} - The updated builder with the new case added.
     */
    case: (<K extends Remaining>(match: K, handler: R | (() => R)) => SwitchCaseBuilder<T, R, Exclude<Remaining, K>>) & ((match: (val: T) => boolean, handler: R | ((val: T) => R)) => SwitchCaseBuilder<T, R, Remaining>);
    /**
     * Adds a default handler for unmatched cases.
     *
     * @param {(val: T) => R} handler - A function to handle unmatched cases.
     * @returns {SwitchCaseBuilder<T, R, never>} - The updated builder with the default handler added.
     */
    default: (handler: (val: T) => R) => SwitchCaseBuilder<T, R, never>;
    /**
     * Ensures all cases are handled and returns the result.
     *
     * @returns {Remaining extends never ? R : never} - The result of the matched case or an error if cases are missing.
     */
    exhaustive: () => Remaining extends never ? R : never;
    /**
     * Executes the switch-case structure and returns the result.
     *
     * @returns {R} - The result of the matched case or the default handler.
     */
    run: () => R;
}
/**
 * Interface for building a discriminated union switch-case structure with fluent API.
 *
 * @template T - The type of the value being matched.
 * @template K - The discriminator key.
 * @template R - The return type of the handler functions.
 * @template Remaining - The remaining discriminator values that can be matched.
 */
interface DiscriminatedUnionSwitchCaseBuilder<T, K extends keyof T, R, Remaining extends string | number | symbol = string | number | symbol> {
    /**
     * Adds a case for a specific discriminator value.
     *
     * @template V - The discriminator value.
     * @param {V} value - The discriminator value to match.
     * @param {(val: VariantOf<T, K, V>) => R} handler - Handler for this case.
     * @returns {DiscriminatedUnionSwitchCaseBuilder<T, K, R, Exclude<Remaining, V>>}
     */
    case: <V extends Remaining>(value: V, handler: (val: VariantOf<T, K, V>) => R) => DiscriminatedUnionSwitchCaseBuilder<T, K, R, Exclude<Remaining, V>>;
    /**
     * Adds a default handler for unmatched cases.
     *
     * @param {(val: T) => R} handler - Handler for unmatched cases.
     * @returns {DiscriminatedUnionSwitchCaseBuilder<T, K, R, never>}
     */
    default: (handler: (val: T) => R) => DiscriminatedUnionSwitchCaseBuilder<T, K, R, never>;
    /**
     * Executes the switch-case structure and returns the result.
     *
     * @returns {R} - The result of the matched case or the default handler.
     */
    run: () => R;
}

declare function switchCase<T extends string | number | symbol, R>(value: T, cases: {
    [K in T]: R | (() => R);
}, defaultHandler?: (val: T) => R): R;
declare function switchCase<T, K extends keyof T, V extends T[K] & (string | number), R>(value: T, discriminator: K, cases: {
    [P in V]: R | ((val: T & {
        [Q in K]: P;
    }) => R);
}, defaultHandler?: (val: T) => R): R;
declare function switchCase<T, R>(value: T, cases: Record<string, CaseHandler<T, R>>, defaultHandler?: (val: T) => R): R;
declare function switchCase<T, R>(value: T, cases: Array<{
    match: (val: T) => boolean;
    handler: R | ((val: T) => R);
}>, defaultHandler?: (val: T) => R): R;
declare function switchCase<T extends string | number | symbol, R>(value: T): SwitchCaseBuilder<T, R, T>;
declare function switchCase<T, R>(value: T): SwitchCaseBuilder<T, R, never>;
declare function switchCase<T, K extends keyof T, R>(value: T, discriminator: K): DiscriminatedUnionSwitchCaseBuilder<T, K, R, T[K] & (string | number | symbol)>;
declare function assertUnreachable(value: never): never;

export { assertUnreachable, switchCase };
