@scale-codec/enum
Version:
Simple JavaScript abstraction around Rust Enums
70 lines (57 loc) • 1.94 kB
TypeScript
/**
* 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 { }