iron-enum
Version:
Rust like enums for Typescript
812 lines • 25.3 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.
* - If the payload is an object with only optional properties, the payload is optional.
* - Otherwise, the constructor requires the payload.
*/
type RequiredKeys<T extends object> = {
[K in keyof T]-?: {} extends Pick<T, K> ? never : K;
}[keyof T];
type HasOnlyOptionalObjectKeys<T> = T extends object ? [RequiredKeys<T>] extends [never] ? true : false : false;
type VariantConstructor<Default, K extends string, ALL extends VariantsRecord> = [
Default
] extends [undefined] ? () => IronEnumVariant<K, Default, ALL> : HasOnlyOptionalObjectKeys<Default> extends true ? (data?: Default) => 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