UNPKG

@scale-codec/enum

Version:
70 lines (57 loc) 1.94 kB
/** * Tagged union in TypeScript. * * @packageDocumentation */ export declare type Enumerate<E extends EnumRecord> = { [Tag in keyof E]: E[Tag] extends infer Content extends [] | [any] ? Variant<E, Tag & string, Content> : never; }[keyof E]; export declare type EnumOf<V extends VariantAny> = V extends Variant<infer E, any, any> ? E : never; export declare type EnumRecord = Record<string, [] | [any]>; /** * Tagged union in TypeScript. * * @packageDocumentation */ declare const enumTags: unique symbol; /** * Rust's `Option<T>` analog * * @example * * ```ts * const maybeString: RustOption<string> = variant('None') * ``` */ export declare type RustOption<T> = Enumerate<{ None: []; Some: [T]; }>; /** * Rust's `Result<Ok, Err>` analog * * @example * * ```ts * const file: RustResult<string, Error> = variant('Ok', 'file contents') * ``` */ export declare type RustResult<Ok, Err> = Enumerate<{ Ok: [Ok]; Err: [Err]; }>; export declare interface Variant<in out E extends EnumRecord, Tag extends string, in out Content extends [] | [any] = []> { [enumTags]: E; readonly tag: Tag; readonly content: Content extends [infer C] ? C : undefined; readonly unit: Content extends [] ? true : false; readonly as: <T extends keyof E>(tag: T) => [T, Content] extends [Tag, [infer C]] ? C : never; } export declare const variant: VariantFactoryFn; export declare type VariantAny = Variant<any, any, any>; export declare interface VariantFactoryFn { <V extends VariantAny>(...args: VariantToFactoryArgs<V>): V; <E extends EnumRecord>(...args: VariantToFactoryArgs<Enumerate<E>>): Enumerate<E>; } export declare type VariantToFactoryArgs<V extends VariantAny> = V extends Variant<any, infer Tag, infer Content> ? Content extends [infer C] ? [tag: Tag, content: C] : [tag: Tag] : never; export { }