/**
 * The library's only entrypoint. Get started with `Member` and `create`.
 *
 * @example
 * import { Member, create } from "@unsplash/sum-types"
 *
 * type Weather
 *   = Member<"Sun">
 *   | Member<"Rain", number>
 *
 * const { mk: { Sun, Rain }, match } = create<Weather>()
 *
 * const getRainfall = match({
 *   Rain: n => `${n}mm`,
 *   Sun: () => "none",
 * })
 *
 * const todayWeather = Rain(5)
 *
 * getRainfall(todayWeather) // "5mm"
 *
 * @since 0.1.0
 */
/**
 * Symbol used to index a sum type and access its tag. Not exposed with the
 * intention that consumers make use of (de)serialization.
 */
declare const tagKey: unique symbol;
declare type TagKey = typeof tagKey;
/**
 * Symbol used to index a sum type and access its tag. Not exposed with the
 * intention that consumers make use of (de)serialization.
 */
declare const valueKey: unique symbol;
declare type ValueKey = typeof valueKey;
/**
 * The `Member` type represents a single member of a sum type given a name and
 * an optional monomorphic value. A sum type is formed by unionizing these
 * members.
 *
 * @example
 * import { Member } from "@unsplash/sum-types"
 *
 * type Weather
 *   = Member<"Sun">
 *   | Member<"Rain", number>
 *
 * @since 0.1.0
 */
export interface Member<K extends string = never, A = null> {
    readonly [tagKey]: K;
    readonly [valueKey]: A;
}
/**
 * @internal
 */
export declare type AnyMember = Member<string, unknown>;
declare type Tag<A extends AnyMember> = A[TagKey];
declare type Value<A extends AnyMember> = A[ValueKey];
declare type ValueByTag<A extends AnyMember, K extends Tag<A>> = Value<Extract<A, Member<K, unknown>>>;
/**
 * A constructor is either `A -> B` or, if it's nullary, directly `B`.
 *
 * Indexes a sum union by the member tag to determine the constructor shape.
 * The third type argument can be inferred via its default.
 *
 * @internal
 */
export declare type Constructor<A extends AnyMember, K extends Tag<A>, V = ValueByTag<A, K>> = [V] extends [null] ? A : (x: V) => A;
/**
 * Build a constructor for a member. If the member is nullary it won't be a
 * function but a plain value.
 *
 * @internal
 */
export declare const mkConstructor: <A extends AnyMember = never>() => <T extends Tag<A>>(k: T) => Constructor<A, T, ValueByTag<A, T>>;
declare type Constructors<A extends AnyMember> = {
    readonly [V in A as Tag<V>]: Constructor<A, Tag<V>>;
};
/**
 * Symbol for declaring a wildcard case in a {@link match} expression.
 *
 * @example
 * import { Member, create, _ } from "@unsplash/sum-types"
 *
 * type Weather
 *   = Member<"Sun">
 *   | Member<"Rain", number>
 *   | Member<"Clouds">
 *   | Member<"Overcast", string>
 *
 * const Weather = create<Weather>()
 *
 * const getSun = Weather.match({
 *   Sun: () => "sun",
 *   Overcast: () => "partial sun",
 *   [_]: () => "no sun",
 * })
 *
 * assert.strictEqual(getSun(Weather.mk.Sun), "sun")
 * assert.strictEqual(getSun(Weather.mk.Clouds), "no sun")
 *
 * @since 0.1.0
 */
export declare const _: unique symbol;
/**
 * Ensures that a {@link match} expression covers all cases.
 */
declare type CasesExhaustive<A extends AnyMember, B> = {
    readonly [V in A as Tag<V>]: (val: Value<V>) => B;
};
declare type CasesXExhaustive<A extends AnyMember, B> = {
    readonly [V in A as Tag<V>]: B;
};
/**
 * Enables a {@link match} expression to cover only some cases provided a
 * wildcard case is declared with which to match the remaining cases.
 */
declare type CasesWildcard<A extends AnyMember, B> = {
    readonly [K in keyof CasesExhaustive<A, B>]?: CasesExhaustive<A, B>[K];
} & {
    readonly [_]: () => B;
};
declare type CasesXWildcard<A extends AnyMember, B> = {
    readonly [K in keyof CasesXExhaustive<A, B>]?: CasesXExhaustive<A, B>[K];
} & {
    readonly [_]: B;
};
/**
 * Ensures that a {@link match} expression either covers all cases or contains
 * a wildcard for matching the remaining cases.
 */
declare type Cases<A extends AnyMember, B> = CasesWildcard<A, B> | CasesExhaustive<A, B>;
declare type CasesX<A extends AnyMember, B> = CasesXWildcard<A, B> | CasesXExhaustive<A, B>;
declare type ReturnTypes<A extends Record<any, (...xs: ReadonlyArray<any>) => unknown>> = ReturnType<A[keyof A]>;
/**
 * @internal
 */
export declare type MatchW<A extends AnyMember> = <B extends Cases<A, unknown>>(fs: B) => (x: A) => ReturnTypes<B>;
/**
 * @internal
 */
export declare type MatchXW<A extends AnyMember> = <B extends CasesX<A, unknown>>(fs: B) => (x: A) => B[keyof B];
/**
 * @internal
 */
export declare type Match<A extends AnyMember> = <B>(fs: Cases<A, B>) => (x: A) => B;
/**
 * @internal
 */
export declare type MatchX<A extends AnyMember> = <B>(fs: CasesX<A, B>) => (x: A) => B;
/**
 * The output of `create`, providing constructors and pattern matching.
 *
 * @internal
 */
export interface Sum<A extends AnyMember> {
    /**
     * An object of constructors for the sum type's members.
     *
     * @since 0.1.0
     */
    readonly mk: Constructors<A>;
    /**
     * Pattern match against each member of a sum type. All members must
     * exhaustively be covered unless a wildcard (@link \_) is present.
     *
     * @example
     * match({
     *   Rain: (n) => `It's rained ${n} today!`,
     *   [_]: () => "Nice weather today.",
     * })
     *
     * @since 0.1.0
     */
    readonly match: Match<A>;
    /**
     * Pattern match against each member of a sum type. All members must
     * exhaustively be covered unless a wildcard (@link \_) is present. Unionises
     * the return types of the branches, hence the "W" suffix ("widen").
     *
     * @example
     * matchW({
     *   Sun: () => 123,
     *   [_]: () => "the return types can be different",
     * })
     *
     * @since 0.1.0
     */
    readonly matchW: MatchW<A>;
    /**
     * Pattern match against each member of a sum type strictly, hence the "X"
     * suffix ("strict"). All members must exhaustively be covered unless a
     * wildcard (@link \_) is present.
     *
     * @example
     * matchX({
     *   Sun: 123,
     *   [_]: 456,
     * })
     *
     * @since 0.4.0
     */
    readonly matchX: MatchX<A>;
    /**
     * Pattern match against each member of a sum type strictly, hence the "X"
     * suffix ("strict"). All members must exhaustively be covered unless a
     * wildcard (@link \_) is present. Unionises the return types of the branches,
     * hence the "W" suffix ("widen").
     *
     * @example
     * matchXW({
     *   Sun: 123,
     *   [_]: "the return types can be different",
     * })
     *
     * @since 0.4.0
     */
    readonly matchXW: MatchXW<A>;
}
/**
 * Create runtime constructors and pattern matching functions for a given sum
 * type.
 *
 * @example
 * import { Member, create } from "@unsplash/sum-types"
 *
 * type Weather
 *   = Member<"Sun">
 *   | Member<"Rain", number>
 *
 * // Depending upon your preferences you may prefer to destructure the
 * // returned object or effectively namespace it:
 * const { mk: { Sun, Rain }, match } = create<Weather>()
 * const Weather = create<Weather>()
 *
 * @since 0.1.0
 */
export declare const create: <A extends AnyMember>() => Sum<A>;
/**
 * The serialized representation of a sum type, isomorphic to the sum type
 * itself.
 *
 * @since 0.1.1
 */
export declare type Serialized<A> = A extends AnyMember ? readonly [Tag<A>, Value<A>] : never;
/**
 * Serialize any sum type member into a tuple of its discriminant tag and its
 * value (if any). It is recommended that you do this for any persistent data
 * storage instead of relying upon how the library internally structures this
 * data, which is an implementation detail. Reversible by `deserialize`.
 *
 * @since 0.1.0
 */
export declare const serialize: <A extends AnyMember>(x: A) => Serialized<A>;
/**
 * Deserialize any prospective sum type member, represented by a tuple of its
 * discriminant tag and its value (if any), into its programmatic data
 * structure. Reversible by `serialize`.
 *
 * @since 0.1.0
 */
export declare const deserialize: <A extends AnyMember>(x: Sum<A>) => (y: Serialized<A>) => A;
/**
 * Refine a foreign value to a sum type member given its key and a refinement to
 * its value.
 *
 * This is a low-level primitive. Instead consider `@unsplash/sum-types-io-ts`.
 *
 * @example
 * import { Member, create, is } from "@unsplash/sum-types"
 *
 * type Weather
 *   = Member<"Sun">
 *   | Member<"Rain", number>
 * const Weather = create<Weather>()
 *
 * assert.strictEqual(
 *   is<Weather>()("Rain")((x): x is number => typeof x === 'number')(Weather.mk.Rain(123)),
 *   true,
 * )
 *
 * @since 0.4.0
 */
export declare const is: <A extends AnyMember>() => <B extends Tag<A>>(k: B) => (f: (mv: unknown) => mv is ValueByTag<A, B>) => (x: unknown) => x is A;
export {};
//# sourceMappingURL=index.d.ts.map