iron-enum
Version: 
Rust like enums for Typescript
807 lines • 24.9 kB
TypeScript
/**
 * IronEnum – Zero-dependency Rust-style tagged-union helpers for TypeScript.
 *
 * A small utility to build runtime representations of discriminated unions,
 * with type-safe pattern matching and ergonomic Result/Option types.
 *
 * @example
 * // Define an enum
 * const Status = IronEnum<{
 * 		Loading: undefined;
 * 		Ready: { finishedAt: Date };
 * 		Error: { message: string; code: number };
 * }>();
 *
 * // Create instances
 * const s1 = Status.Loading();
 * const s2 = Status.Ready({ finishedAt: new Date() });
 *
 * // Narrow using .is()
 * if (s2.is("Ready")) {
 * 		s2.data.finishedAt.toISOString();
 * }
 *
 * // Match with fallback
 * const msg = s2.match({
 * 		Loading: () => "Working",
 * 		Ready: ({ finishedAt }) => finishedAt.toISOString(),
 * 		_: () => "Unknown"
 * });
 *
 * // Exhaustive match (no fallback allowed)
 * const iso = s2.matchExhaustive({
 * 		Loading: () => "n/a",
 * 		Ready: ({ finishedAt }) => finishedAt.toISOString(),
 * 		Error: () => "n/a",
 * });
 *
 * @example
 * // Result and Option usage
 * const R = Result<number, string>();
 * const r1 = R.Ok(42);
 * const r2 = R.Err("nope");
 * const val = r1.unwrap_or(0); // 42
 *
 * const O = Option<number>();
 * const some = O.Some(7);
 * const none = O.None();
 * const out = some.map(x => x * 2).unwrap(); // 14
 */
/**
 * Structure of enum variants.
 *
 * Each key is a variant name and its value is the payload for that variant.
 * Use `undefined` for variants without associated data.
 *
 * @example
 * type MyVariants = {
 * 		Unit: undefined;
 * 		Tuple: [string, number];
 * 		Record: { id: string };
 * }
 */
export type VariantsRecord = {
    readonly [K in Exclude<string, "_">]: unknown;
};
/**
 * Union of all possible enum variant instances for a given `VariantsRecord`.
 *
 * This is useful for function parameters that accept any variant instance.
 * This type is typically accessed via the `_.typeOf` property on a factory.
 *
 * @example
 * const Status = IronEnum<{ Ok: string; Err: Error }>();
 *
 * // The `_.typeOf` property provides this union type.
 * function logStatus(s: typeof Status._.typeOf) {
 * 		// s is: IronEnumVariantUnion<{ Ok: string; Err: Error }>
 * 		console.log(s.tag);
 * }
 */
export type IronEnumVariantUnion<ALL extends VariantsRecord> = {
    [K in keyof ALL & string]: IronEnumVariant<K, ALL[K], ALL>;
}[keyof ALL & string];
/**
 * Constructor signature for a variant based on its payload type.
 *
 * - If the payload type is `undefined`, the constructor is nullary.
 * - Otherwise, the constructor requires the payload.
 */
type VariantConstructor<Default, K extends string, ALL extends VariantsRecord> = [
    Default
] extends [undefined] ? () => IronEnumVariant<K, Default, ALL> : (data: Default) => IronEnumVariant<K, Default, ALL>;
/**
 * Return type calculation used by `if` and `ifNot`.
 *
 * Produces a boolean when both callbacks return `void`.
 * Otherwise, returns the union of defined callback return types plus boolean.
 */
type IfReturn<RIf, RElse> = [RIf, RElse] extends [void, void] ? boolean : RIf extends void ? boolean | Exclude<RElse, void> : RElse extends void ? boolean | Exclude<RIf, void> : Exclude<RIf, void> | Exclude<RElse, void>;
/**
 * A single constructed enum variant instance with its discriminant, payload,
 * a back-reference to the factory that created it, and matching utilities.
 *
 * @template TAG     The discriminant string literal
 * @template PAYLOAD The payload type carried by this variant
 * @template ALL     The full `VariantsRecord` for the enum
 */
export type IronEnumVariant<TAG extends keyof ALL & string, PAYLOAD, ALL extends VariantsRecord> = {
    /** Discriminant of the variant. */
    readonly tag: TAG;
    /** Payload carried by the variant. */
    readonly data: PAYLOAD;
    /**
     * The factory object this instance originated from.
     *
     * @example
     * const loading = Status.Loading();
     * // Create a new variant from the same factory
     * const ready = loading.instance.Ready({ finishedAt: new Date() });
     */
    readonly instance: IronEnumFactory<ALL>;
} & EnumMethods<ALL, TAG>;
/**
 * Serializable wire format for a variant instance.
 *
 * Use with `JSON.stringify` and `Enum._.parse` / `Enum._.fromJSON` /
 * `Enum._.reviver` to move values across the wire safely.
 *
 * @example
 * const s = Status.Error({ message: "oops", code: 500 });
 * const json = JSON.stringify(s);
 * // json === '{"tag":"Error","data":{"message":"oops","code":500}}'
 */
export type IronEnumWireFormat<ALL extends VariantsRecord> = {
    [K in keyof ALL & string]: {
        tag: K;
        data: ALL[K];
    };
}[keyof ALL & string];
/**
 * Helper to exclude a specific variant from the union by its tag.
 */
type ExcludeVariant<ALL extends VariantsRecord, K extends keyof ALL & string> = Exclude<IronEnumVariantUnion<ALL>, IronEnumVariant<K, ALL[K], ALL>>;
/**
 * Methods present on each variant instance.
 *
 * Includes:
 * - `toJSON` for structured logging/serialization.
 * - `is` / `if` / `ifNot` for quick predicates.
 * - `match` / `matchAsync` for flexible pattern matching.
 * - `matchExhaustive` for compile-time exhaustive handling.
 */
export interface EnumMethods<ALL extends VariantsRecord, TAG extends keyof ALL & string> {
    /**
     * Convert the instance into `{ tag, data }` for JSON or debugging.
     * Automatically called by `JSON.stringify`.
     *
     * @example
     * const s = Status.Ready({ finishedAt: new Date() });
     * const json = JSON.stringify(s);
     * // json === '{"tag":"Ready","data":{...}}'
     */
    toJSON(): {
        readonly tag: TAG;
        readonly data: ALL[TAG];
    };
    /**
     * Predicate that narrows the variant type on success.
     *
     * @example
     * if (state.is("Ready")) {
     * // state.data is narrow to Ready payload
     * state.data.finishedAt.toISOString();
     * }
     */
    is<K extends keyof ALL & string>(key: K): this is IronEnumVariant<K, ALL[K], ALL>;
    /**
     * Execute a callback when the discriminant equals `key`.
     *
     * When no callbacks are provided, acts as a boolean predicate.
     * When callbacks are provided, returns `true` or the callback's
     * result on success, and `false` or the failure callback's
     * result on failure.
     *
     * The `failure` callback receives a type-safe union of all
     * variants *except* the one being checked.
     *
     * @example
     * // As a predicate
     * if (state.if("Loading")) {
     * 		// ...
     * }
     *
     * // With a success callback
     * state.if("Ready", (data) => {
     * 		console.log(data.finishedAt);
     * });
     *
     * // With both callbacks to extract a value
     * const message = state.if(
     * 		"Error",
     * 		(data) => `Error: ${data.message}`,
     * 		(other) => `Status: ${other.tag}` // other is Loading | Ready
     * );
     */
    if<K extends keyof ALL & string, RIf = void, RElse = void>(key: K, success?: (payload: ALL[K], self: IronEnumVariant<K, ALL[K], ALL>) => RIf, failure?: (self: ExcludeVariant<ALL, K>) => RElse): IfReturn<RIf, RElse>;
    /**
     * Execute a callback when the discriminant does NOT equal `key`.
     *
     * The `success` callback receives a type-safe union of all
     * variants *except* the one being checked.
     *
     * @example
     * // As a predicate
     * if (state.ifNot("Error")) {
     * 		// state is Loading | Ready
     * }
     *
     * // With a success callback
     * state.ifNot("Loading", (other) => {
     * 		// other is Ready | Error
     * 		console.log(`Not loading: ${other.tag}`);
     * });
     */
    ifNot<K extends keyof ALL & string, RIf = void, RElse = void>(key: K, success?: (self: ExcludeVariant<ALL, K>) => RIf, failure?: (payload: ALL[K], self: IronEnumVariant<K, ALL[K], ALL>) => RElse): IfReturn<RIf, RElse>;
    /**
     * Pattern matching with optional `_` fallback arm.
     *
     * Use when some variants can be handled together via a fallback.
     *
     * @example
     * // Exhaustive match
     * const httpStatus = state.match({
     * 		Loading: () => 202,
     * 		Ready: () => 200,
     * 		Error: ({ code }) => code,
     * });
     *
     * // With a fallback
     * const message = state.match({
     * 		Error: ({ message }) => message,
     * 		_: (self) => `Current state: ${self.tag}`,
     * });
     */
    match<A extends MatchFns<ALL>>(callbacks: A): MatchResult<A>;
    /**
     * Asynchronous pattern matching with optional `_` fallback arm.
     * All callbacks must return a `Promise`.
     *
     * @example
     * const data = await state.matchAsync({
     * 		Loading: async () => fetch("/data"),
     * 		Ready: async (data) => data.finishedAt,
     * 		_: async () => null
     * });
     */
    matchAsync<A extends MatchFnsAsync<ALL>>(callbacks: A): Promise<MatchResult<A>>;
    /**
     * Exhaustive pattern matching. All variants must be handled.
     *
     * No `_` fallback is allowed. Compilation fails if a case is missing.
     *
     * @example
     * const message = state.matchExhaustive({
     * 		Loading: () => "Still loading...",
     * 		Ready: ({ finishedAt }) => `Done at ${finishedAt}`,
     * 		Error: ({ message }) => `Failed: ${message}`,
     * });
     */
    matchExhaustive<A extends ExhaustiveFns<ALL>>(callbacks: A): MatchResult<A>;
}
type NonOptional<T> = {
    [K in keyof T]-?: T[K];
};
/** Map each tag to a synchronous handler `(payload, self) => R`. */
type ObjectToFunctionMapBase<T extends VariantsRecord, R> = {
    [K in keyof T]?: (payload: T[K], self: IronEnumVariant<K & string, T[K], T>) => R;
};
/** Sync handler options. */
type ObjectToFunctionMap<T extends VariantsRecord> = ObjectToFunctionMapBase<T, any>;
/** Async handler options. */
type ObjectToFunctionMapAsync<T extends VariantsRecord> = ObjectToFunctionMapBase<T, Promise<any>>;
/**
 * Valid sync match configurations:
 * 1) Provide all tags, or
 * 2) Provide partial tags plus `_` fallback.
 */
type MatchFns<X extends VariantsRecord> = NonOptional<ObjectToFunctionMap<X>> | (ObjectToFunctionMap<X> & {
    _: (self: IronEnumVariantUnion<X>) => any;
});
/**
 * Valid async match configurations:
 * 1) Provide all tags, or
 * 2) Provide partial tags plus `_` fallback.
 */
type MatchFnsAsync<X extends VariantsRecord> = NonOptional<ObjectToFunctionMapAsync<X>> | (ObjectToFunctionMapAsync<X> & {
    _: (self: IronEnumVariantUnion<X>) => Promise<any>;
});
/** Exhaustive mapping: all tags required, no `_` fallback allowed. */
type ExhaustiveFns<X extends VariantsRecord> = {
    [K in keyof X & string]: (payload: X[K], self: IronEnumVariant<K, X[K], X>) => any;
};
/** Extract the unified return type of a match dispatch. */
type MatchResult<A> = A extends {
    [K: string]: (...args: any) => infer R;
} ? R : never;
/**
 * Runtime factory for an enum, where each key is a constructor for its variant.
 *
 * @example
 * const Status = IronEnum<{
 * Loading: undefined;
 * Ready: { count: number };
 * }>();
 *
 * const s1 = Status.Loading(); // { tag: "Loading", data: undefined }
 * const s2 = Status.Ready({ count: 1 }); // { tag: "Ready", data: { count: 1 } }
 */
export type IronEnumFactory<ALL extends VariantsRecord> = {
    [K in keyof ALL & string]: VariantConstructor<ALL[K], K, ALL>;
} & {
    /**
     * Utilities and [TYPE ONLY] metadata exposed via the `_` property.
     *
     * The fields marked [TYPE ONLY] exist only for type access in code and do not
     * exist at runtime. They intentionally evaluate to `never` at runtime.
     */
    _: EnumProperties<ALL, {}>;
};
/**
 * Utility metadata exposed on the factory via `_`.
 *
 * Includes parsers and [TYPE ONLY] accessors for tags, payload union, and
 * the union instance type.
 */
export type EnumProperties<ALL extends VariantsRecord, AddedProps> = {
    /**
     * [TYPE ONLY] Union of tag names.
     *
     * @example
     * const Status = IronEnum<{ A: 0; B: 1 }>();
     * type StatusTags = typeof Status._.typeTags; // "A" | "B"
     */
    readonly typeTags: keyof ALL & string;
    /**
     * [TYPE ONLY] Union of payload values.
     *
     * @example
     * const Status = IronEnum<{ A: 0; B: 1 }>();
     * type StatusData = typeof Status._.typeData; // 0 | 1
     */
    readonly typeData: ALL[keyof ALL];
    /**
     * [TYPE ONLY] The generic json format exported by `toJSON` and parsed by `_.parse`.
     *
     * @example
     * const Status = IronEnum<{ A: 0; B: 1 }>();
     *
     * function process(s: typeof Status._.typeJson) {
     * 		const p = Status._.parse(s);
     * }
     *
     * process(Status.A(0).toJSON());
     *
     */
    readonly typeJson: IronEnumWireFormat<ALL>;
    /**
     * [TYPE ONLY] Union of all variant instances for this enum.
     * This is the main type to use in function signatures or return statements.
     *
     * @example
     * const Status = IronEnum<{ A: 0; B: 1 }>();
     *
     * function process(s: typeof Status._.typeOf) {
     * // ...
     * }
     *
     * process(Status.A(0));
     */
    readonly typeOf: IronEnumVariantUnion<ALL> & AddedProps;
    /**
     * Parse `{ tag, data }` into a variant instance.
     * If the keys where provided to the original function call then throws when the tag is not recognized by this factory.
     *
     * @example
     * const data = { tag: "Ready", data: { finishedAt: new Date() } } as const;
     * const s = Status._.parse(data);
     * if (s.is("Ready")) { ... }
     */
    parse<TAG extends keyof ALL & string>(dataObj: ALL[TAG] extends undefined ? {
        tag: TAG;
        data?: ALL[TAG];
    } : {
        tag: TAG;
        data: ALL[TAG];
    }): IronEnumVariant<TAG, ALL[TAG], ALL>;
    /**
     * Alias of `parse`. Convenient for deserializers.
     * @see parse
     */
    fromJSON<TAG extends keyof ALL & string>(dataObj: ALL[TAG] extends undefined ? {
        tag: TAG;
        data?: ALL[TAG];
    } : {
        tag: TAG;
        data: ALL[TAG];
    }): IronEnumVariant<TAG, ALL[TAG], ALL>;
    /**
     * JSON.parse reviver. Pass as the reviver to automatically convert
     * nested `{ tag, data }` shapes for this enum.
     *
     * @example
     * const text = '{"tag":"Ready","data":{...}}';
     * const s = JSON.parse(text, (k, v) => Status._.reviver(v));
     * // s is now a full Status.Ready variant instance
     */
    reviver(obj: unknown): IronEnumVariantUnion<ALL> | unknown;
};
/**
 * Create a new enum factory.
 *
 * @param args - Optional arguments.
 * @param args.keys - An array of variant keys. Providing this skips the
 * Proxy-based implementation for a faster, pre-bound factory.
 *
 * @example
 * // Dynamic (Proxy-based, slower)
 * const Status = IronEnum<{
 * 		A: undefined;
 * 		B: undefined;
 * }>();
 *
 * // Pre-bound (Fast, no Proxy)
 * const FastStatus = IronEnum<{
 * 		A: undefined;
 * 		B: undefined;
 * }>({ keys: ["A", "B"] });
 */
export declare function IronEnum<ALL extends VariantsRecord>(args?: {
    keys?: (keyof ALL & string)[];
}): "_" extends keyof ALL ? "ERROR: '_' is reserved!" : IronEnumFactory<ALL>;
/**
 * Methods common to success-carrying types that allow extracting values,
 * defaults, or lazily computed fallbacks.
 */
type ExtendedRustMethods<T> = {
    /**
     * Return the success value.
     * **Throws** if the variant is `Err` or `None`.
     *
     * @example
     * Ok(1).unwrap(); // 1
     * Err("!").unwrap(); // Throws
     * None().unwrap(); // Throws
     */
    unwrap(): T;
    /**
     * Return the success value or a provided default.
     *
     * @example
     * Ok(1).unwrap_or(0); // 1
     * Err("!").unwrap_or(0); // 0
     * None().unwrap_or(0); // 0
     */
    unwrap_or<R>(value: R): R | T;
    /**
     * Return the success value or the result of a fallback function.
     * The callback is only executed if needed.
     *
     * @example
     * Ok(1).unwrap_or_else(() => 0); // 1
     * Err("!").unwrap_or_else(() => 0); // 0
     * None().unwrap_or_else(() => expensive_calc()); // 0
     */
    unwrap_or_else<R>(cb: () => R): R | T;
};
/**
 * Result-specific helpers for mapping and chaining.
 */
type ResultMethods<ALL extends {
    Ok: unknown;
    Err: unknown;
}> = {
    /**
     * Convert `Result<T,E>` to `Option<T>`, dropping the error.
     *
     * @example
     * Ok(1).ok(); // Some(1)
     * Err("!").ok(); // None()
     */
    ok(): OptionVariant<{
        Some: ALL["Ok"];
        None: undefined;
    }>;
    /**
     * Predicate for `Ok` variant.
     *
     * @example
     * if (myResult.isOk()) { ... }
     */
    isOk(): boolean;
    /**
     * Predicate for `Err` variant.
     *
     * @example
     * if (myResult.isErr()) { ... }
     */
    isErr(): boolean;
    /**
     * Map the `Ok` value, leaving `Err` untouched.
     *
     * @example
     * Ok(1).map(x => x + 1); // Ok(2)
     * Err("!").map(x => x + 1); // Err("!")
     */
    map<U>(f: (t: ALL["Ok"]) => U): ResultVariant<{
        Ok: U;
        Err: ALL["Err"];
    }>;
    /**
     * Map the `Err` value, leaving `Ok` untouched.
     *
     * @example
     * Ok(1).mapErr(x => x + "!"); // Ok(1)
     * Err("!").mapErr(x => x + "!"); // Err("!!")
     */
    mapErr<F>(f: (e: ALL["Err"]) => F): ResultVariant<{
        Ok: ALL["Ok"];
        Err: F;
    }>;
    /**
     * Chain a new `Result`-returning operation when `Ok`.
     * Also known as `flatMap`.
     *
     * @example
     * const safeDivide = (n: number) => n === 0 ? Err("div by 0") : Ok(10 / n);
     *
     * Ok(5).andThen(safeDivide); // Ok(2)
     * Ok(0).andThen(safeDivide); // Err("div by 0")
     * Err("!").andThen(safeDivide); // Err("!")
     */
    andThen<U>(f: (t: ALL["Ok"]) => ResultVariant<{
        Ok: U;
        Err: ALL["Err"];
    }>): ResultVariant<{
        Ok: U;
        Err: ALL["Err"];
    }>;
};
/**
 * A Result instance (Ok or Err) with extraction and mapping helpers.
 *
 * This type is invariant, meaning `Result<T, never>` is not assignable
 * to `Result<T, string>`.
 *
 * To accept `Result` in a function, either use a specific factory:
 * @example
 * const MyResult = Result<string, Error>();
 * function process(r: typeof MyResult._.typeOf) { ... }
 *
 * // Or make the function generic:
 * function process<T, E>(r: ResultVariant<{ Ok: T, Err: E }>) { ... }
 */
export type ResultVariant<ALL extends {
    Ok: unknown;
    Err: unknown;
}> = IronEnumVariant<keyof ALL & string, ALL[keyof ALL], ALL> & ExtendedRustMethods<ALL["Ok"]> & ResultMethods<ALL>;
/**
 * Factory for creating Ok and Err variants plus metadata via `_`.
 *
 * @example
 * const R = Result<number, string>();
 * const r1 = R.Ok(1);
 * const r2 = R.Err("nope");
 */
export type ResultFactory<ALL extends {
    Ok: unknown;
    Err: unknown;
}> = {
    Ok(data: ALL["Ok"]): IronEnumVariant<"Ok", ALL["Ok"], ALL> & ExtendedRustMethods<ALL["Ok"]> & ResultMethods<ALL>;
    Err(data: ALL["Err"]): IronEnumVariant<"Err", ALL["Err"], ALL> & ExtendedRustMethods<ALL["Ok"]> & ResultMethods<ALL>;
    _: EnumProperties<ALL, ExtendedRustMethods<ALL["Ok"]> & ResultMethods<ALL>>;
};
/**
 * Create a typed Result factory `<T,E>`.
 *
 * @example
 * const StringResult = Result<string, Error>();
 * const r1 = StringResult.Ok("hello");
 *
 * function process(r: typeof StringResult._.typeOf) {
 * // ...
 * }
 */
export declare const Result: <T, E>() => ResultFactory<{
    Ok: T;
    Err: E;
}>;
/**
 * Convenience Ok constructor for ad-hoc success values.
 * The `Err` type is `never`.
 *
 * @example
 * const r = Ok(123); // ResultVariant<{ Ok: number, Err: never }>
 */
export declare const Ok: <T>(value: T) => ResultVariant<{
    Ok: T;
    Err: never;
}>;
/**
 * Convenience Err constructor for ad-hoc error values.
 * The `Ok` type is `never`.
 *
 * @example
 * const r = Err("oops"); // ResultVariant<{ Ok: never, Err: string }>
 */
export declare const Err: <E>(error: E) => ResultVariant<{
    Ok: never;
    Err: E;
}>;
/**
 * Option-specific helpers for converting to Result, mapping, chaining, and
 * basic predicates.
 */
type OptionMethods<OK> = {
    /**
     * Convert `Some(T)` to `Ok(T)` or `None` to `Err(E)`.
     *
     * @example
     * Some(1).ok_or("!"); // Ok(1)
     * None().ok_or("!"); // Err("!")
     */
    ok_or<E>(err: E): ResultVariant<{
        Ok: OK;
        Err: E;
    }>;
    /**
     * Convert `Some(T)` to `Ok(T)` or `None` to `Err(E)`
     * using a lazily-computed error.
     *
     * @example
     * Some(1).ok_or_else(() => "!"); // Ok(1)
     * None().ok_or_else(() => "!"); // Err("!")
     */
    ok_or_else<E>(err: () => E): ResultVariant<{
        Ok: OK;
        Err: E;
    }>;
    /**
     * Predicate for `Some` variant.
     *
     * @example
     * if (myOption.isSome()) { ... }
     */
    isSome(): boolean;
    /**
     * Predicate for `None` variant.
     *
     * @example
     * if (myOption.isNone()) { ... }
     */
    isNone(): boolean;
    /**
     * Map the `Some` value, leaving `None` untouched.
     *
     * @example
     * Some(1).map(x => x + 1); // Some(2)
     * None().map(x => x + 1); // None()
     */
    map<U>(f: (t: OK) => U): OptionVariant<{
        Some: U;
        None: undefined;
    }>;
    /**
     * Chain a new `Option`-returning operation when `Some`.
     * Also known as `flatMap`.
     *
     * @example
     * const firstChar = (s: string) => s.length > 0 ? Some(s[0]) : None();
     *
     * Some("hi").andThen(firstChar); // Some("h")
     * Some("").andThen(firstChar); // None()
     * None().andThen(firstChar); // None()
     */
    andThen<U>(f: (t: OK) => OptionVariant<{
        Some: U;
        None: undefined;
    }>): OptionVariant<{
        Some: U;
        None: undefined;
    }>;
    /**
     * Keep `Some` only when the predicate passes.
     *
     * @example
     * Some(2).filter(x => x % 2 === 0); // Some(2)
     * Some(1).filter(x => x % 2 === 0); // None()
     * None().filter(x => x % 2 === 0); // None()
     */
    filter(p: (t: OK) => boolean): OptionVariant<{
        Some: OK;
        None: undefined;
    }>;
};
/**
 * Option instance (Some or None) enriched with extraction and mapping helpers.
 *
 * This type is invariant. See `ResultVariant` for notes on usage.
 */
export type OptionVariant<ALL extends {
    Some: unknown;
    None: undefined;
}> = IronEnumVariant<keyof ALL & string, ALL[keyof ALL], ALL> & ExtendedRustMethods<ALL["Some"]> & OptionMethods<ALL["Some"]>;
/**
 * Factory for creating Some and None variants plus metadata via `_`.
 *
 * @example
 * const O = Option<number>();
 * const s = O.Some(1);
 * const n = O.None();
 */
export type OptionFactory<ALL extends {
    Some: unknown;
    None: undefined;
}> = {
    Some(data: ALL["Some"]): IronEnumVariant<"Some", ALL["Some"], ALL> & ExtendedRustMethods<ALL["Some"]> & OptionMethods<ALL["Some"]>;
    None(): IronEnumVariant<"None", ALL["None"], ALL> & ExtendedRustMethods<ALL["Some"]> & OptionMethods<ALL["Some"]>;
    _: EnumProperties<ALL, ExtendedRustMethods<ALL["Some"]> & OptionMethods<ALL["Some"]>>;
};
/**
 * Create a typed Option factory `<T>`.
 *
 * @example
 * const NumberOption = Option<number>();
 * const s = NumberOption.Some(100);
 *
 * function process(o: typeof NumberOption._.typeOf) {
 * // ...
 * }
 */
export declare const Option: <T>() => OptionFactory<{
    Some: T;
    None: undefined;
}>;
/**
 * Convenience Some constructor for ad-hoc values.
 *
 * @example
 * const s = Some(123); // OptionVariant<{ Some: number, ... }>
 */
export declare const Some: <T>(value: T) => OptionVariant<{
    Some: T;
    None: undefined;
}>;
/**
 * Convenience None constructor.
 * The `Some` type is `never`.
 *
 * @example
 * const n = None(); // OptionVariant<{ Some: never, ... }>
 */
export declare const None: () => OptionVariant<{
    Some: never;
    None: undefined;
}>;
/**
 * Convert exception-throwing code into Result-returning code.
 */
export declare const Try: {
    /**
     * Execute a synchronous function and wrap the outcome.
     * Ok on success, Err with the caught exception on failure.
     */
    sync<X>(cb: () => X): ResultVariant<{
        Ok: X;
        Err: unknown;
    }>;
    /**
     * Execute an asynchronous function and wrap the outcome.
     * Resolves to Ok on success, Err with the caught exception on rejection.
     */
    async<X>(cb: () => Promise<X>): Promise<ResultVariant<{
        Ok: X;
        Err: unknown;
    }>>;
};
/**
 * Transform functions to return Result instead of throwing.
 */
export declare const TryInto: {
    /**
     * Wrap a synchronous function. The wrapper never throws.
     */
    sync<X, Y extends any[]>(cb: (...args: Y) => X): (...args: Y) => ResultVariant<{
        Ok: X;
        Err: unknown;
    }>;
    /**
     * Wrap an asynchronous function. The wrapper resolves to Result.
     */
    async<X, Y extends any[]>(cb: (...args: Y) => Promise<X>): (...args: Y) => Promise<ResultVariant<{
        Ok: X;
        Err: unknown;
    }>>;
};
export {};
//# sourceMappingURL=mod.d.ts.map