UNPKG

ts-union

Version:

ADT (sum type) in typescript inspired by ML language family

142 lines (141 loc) 7.16 kB
export interface Const<T> { readonly _const: T; } export interface Generic { opaque: 'Generic is a token type that is going to be replaced with a real type'; } export interface Unit { opaque: 'opaque token for empty payload type'; } export declare type Case<T> = Of<T> | Const<T>; export interface RecordDict { readonly [key: string]: Case<unknown>; } export declare type SingleDataCase = Of<[Unit]> | Const<unknown> | Of<[unknown]>; export interface SingleDataRecordDict { readonly [key: string]: SingleDataCase; } export interface ForbidDefault { default?: never; } export declare type ForbidReservedProps = { readonly if?: never; readonly match?: never; readonly matchWith?: never; readonly T?: never; } & ForbidDefault; export declare type RequiredRecordType = RecordDict & ForbidReservedProps; export declare type SingleDataRecordType = SingleDataRecordDict & ForbidReservedProps; export interface Of<T> { _opaque: T; } export interface Types { (unit: null): Of<[Unit]>; <T = void>(): Of<[T]>; (g: Generic): Of<[Generic]>; <T>(val: T): Const<T>; <T1, T2>(): Of<[T1, T2]>; <T1, T2, T3>(): Of<[T1, T2, T3]>; } export declare const of: Types; export interface UnionVal<Record> { readonly _opaqueToken: Record; } export interface UnionValG<P, Record> { readonly _opaqueToken: Record; readonly _type: P; } export declare type GenericValType<Type, Val> = Val extends UnionValG<infer _Type, infer Rec> ? UnionValG<Type, Rec> : never; export declare type Constructors<Record> = { [T in keyof Record]: CreatorFunc<Record[T], UnionVal<Record>>; }; export declare type ConstructorsG<Record> = { [K in keyof Record]: CreatorFuncG<Record[K], Record>; }; export declare type Cases<Record, Result> = { [T in keyof Record]: MatchCaseFunc<Record[T], Result>; }; export declare type CasesG<Record, Result, P> = { [K in keyof Record]: MatchCaseFuncG<Record[K], Result, P>; }; export declare type CreatorFunc<K, UVal> = K extends Of<infer A> ? A extends [void] ? () => UVal : A extends [Unit] ? UVal : A extends any[] ? (...p: A) => UVal : never : K extends Const<unknown> ? () => UVal : never; export declare type CreatorFuncG<K, Rec> = K extends Of<infer A> ? A extends [void] ? <P = never>() => UnionValG<P, Rec> : A extends [Unit] ? <P = never>() => UnionValG<P, Rec> : A extends [Generic] ? <P>(val: P) => UnionValG<P, Rec> : A extends any[] ? <P = never>(...p: A) => UnionValG<P, Rec> : never : K extends Const<unknown> ? <P = never>() => UnionValG<P, Rec> : never; export declare type MatchCaseFunc<K, Res> = K extends Of<infer A> ? A extends [void] ? () => Res : A extends [Unit] ? () => Res : A extends any[] ? (...p: A) => Res : never : K extends Const<infer C> ? (c: C) => Res : never; export declare type MatchCaseFuncG<K, Res, P> = K extends Of<infer A> ? A extends [void] ? () => Res : A extends [Unit] ? () => Res : A extends [Generic] ? (val: P) => Res : A extends any[] ? (...p: A) => Res : never : K extends Const<infer C> ? (c: C) => Res : never; export declare type MatchCases<Record, Result> = (Cases<Record, Result> & ForbidDefault) | (Partial<Cases<Record, Result>> & { default: (val: UnionVal<Record>) => Result; }); export declare type MatchCasesG<Rec, Result, P> = (CasesG<Rec, Result, P> & ForbidDefault) | (Partial<CasesG<Rec, Result, P>> & { default: (val: UnionValG<P, Rec>) => Result; }); export interface MatchFunc<Record> { <Result>(cases: MatchCases<Record, Result>): (val: UnionVal<Record>) => Result; <Result>(val: UnionVal<Record>, cases: MatchCases<Record, Result>): Result; } export interface MatchFuncG<Record> { <Result, P>(cases: MatchCasesG<Record, Result, P>): (val: UnionValG<P, Record>) => Result; <Result, P>(val: UnionValG<P, Record>, cases: MatchCasesG<Record, Result, P>): Result; } export declare type UnpackFunc<K, Rec> = K extends Of<infer A> ? A extends [void] ? { <R>(val: UnionVal<Rec>, f: () => R): R | undefined; <R>(val: UnionVal<Rec>, f: () => R, els: (v: UnionVal<Rec>) => R): R; } : A extends [Unit] ? { <R>(val: UnionVal<Rec>, f: () => R): R | undefined; <R>(val: UnionVal<Rec>, f: () => R, els: (v: UnionVal<Rec>) => R): R; } : A extends any[] ? { <R>(val: UnionVal<Rec>, f: (...p: A) => R): R | undefined; <R>(val: UnionVal<Rec>, f: (...p: A) => R, els: (v: UnionVal<Rec>) => R): R; } : never : K extends Const<infer С> ? { <R>(val: UnionVal<Rec>, f: (с: С) => R): R | undefined; <R>(val: UnionVal<Rec>, f: (с: С) => R, els: (v: UnionVal<Rec>) => R): R; } : never; export declare type UnpackFuncG<K, Rec> = K extends Of<infer A> ? A extends [void] ? { <R, P>(val: UnionValG<P, Rec>, f: () => R): R | undefined; <R, P>(val: UnionValG<P, Rec>, f: () => R, els: (v: UnionValG<P, Rec>) => R): R; } : A extends [Unit] ? { <R, P>(val: UnionValG<P, Rec>, f: () => R): R | undefined; <R, P>(val: UnionValG<P, Rec>, f: () => R, els: (v: UnionValG<P, Rec>) => R): R; } : A extends [Generic] ? { <R, P>(val: UnionValG<P, Rec>, f: (val: P) => R): R | undefined; <R, P>(val: UnionValG<P, Rec>, f: (val: P) => R, els: (v: UnionValG<P, Rec>) => R): R; } : A extends any[] ? { <R, P>(val: UnionValG<P, Rec>, f: (...p: A) => R): R | undefined; <R, P>(val: UnionValG<P, Rec>, f: (...p: A) => R, els: (v: UnionValG<P, Rec>) => R): R; } : never : K extends Const<infer С> ? { <R, P>(val: UnionValG<P, Rec>, f: (с: С) => R): R | undefined; <R, P>(val: UnionValG<P, Rec>, f: (с: С) => R, els: (v: UnionValG<P, Rec>) => R): R; } : never; export declare type Unpack<Rec> = { [K in keyof Rec]: UnpackFunc<Rec[K], Rec>; }; export declare type UnpackG<Rec> = { [K in keyof Rec]: UnpackFuncG<Rec[K], Rec>; }; declare type UnionDesc<Rec> = { if: Unpack<Rec>; T: UnionVal<Rec>; match: MatchFunc<Rec>; matchWith: Rec extends SingleDataRecordType ? <Other extends SingleDataRecordType, Result>(other: UnionDesc<Other>, matchObj: MatchCasesForTwo<Rec, Other, Result>) => (a: UnionVal<Rec>, b: UnionVal<Other>) => Result : never; } & Constructors<Rec>; export declare type UnionObj<Rec> = UnionDesc<Rec>; export declare type GenericUnionDesc<Rec> = { match: MatchFuncG<Rec>; if: UnpackG<Rec>; T: UnionValG<unknown, Rec>; } & ConstructorsG<Rec>; declare type TypeOfLeg<Leg> = Leg extends Of<infer A> ? A extends [void] | [Unit] ? void : A extends [infer Value] ? Value : A extends Const<infer C> ? C : never : never; export declare type MatchCaseFuncTwo<LegA, LegB, Res> = (a: TypeOfLeg<LegA>, b: TypeOfLeg<LegB>) => Res; export declare type CasesTwo<RecordA, RecordB, Result> = { [KA in keyof RecordA]?: { [KB in keyof RecordB]?: MatchCaseFuncTwo<RecordA[KA], RecordB[KB], Result>; }; }; export declare type MatchCasesForTwo<RecordA, RecordB, Result> = CasesTwo<RecordA, RecordB, Result> & { default: (a: UnionVal<RecordA>, b: UnionVal<RecordB>) => Result; }; export interface UnionFunc { <R extends RequiredRecordType>(record: R): UnionDesc<R>; <R extends RequiredRecordType>(ctor: (g: Generic) => R): GenericUnionDesc<R>; } export declare const Union: UnionFunc; export {};