import { TypeMatcher } from "./matchers" ; private export interface PartialMatchCase < A , R > { private param val param def partMap ( val , def ) : R ; } /**
 * MatchCase is basically a function between category A and R
 */ export interface MatchCase < A , R > { /**
     * Cases handler no default handler, depends on implementation
     */ map ( val ) : R ; } /**
 * SingleCase - map type A to R or fail with an error
 *
 * ```
 * caseWhen(isOne, id). // <- SingleCase
 * caseWhen(isTwo, id). // <- DisjunctionCase, executes previous case and falls back to itself
 * caseWhen(isThree, id). // <- one more DisjunctionCase
 * caseDefault(() => c) // <- DefaultCase - adds default value expression
 * ```
 */ export class SingleCase < M , A extends M , R > implements MatchCase < A , R > , PartialMatchCase < A , R > { constructor ( private readonly match , private readonly handle ) { } partMap ( val , def ) { if ( this . match ( val ) ) { return this . handle ( val ) ; } return def ( ) ; } map ( val ) { return this . partMap ( val , ( ) => { throw new Error ( "No match" ) ; } ) ; } /**
     * Add a disjunction case
     */ caseWhen < N , B extends N , R2 > ( match , handle ) { return new DisjunctionCase ( new SingleCase ( this . match , this . handle ) , new SingleCase ( match , handle ) ) ; } caseDefault < R2 > ( def ) { return new DefaultCase < R | R2 > ( this , def ) ; } } param tailCases param headCase export class DisjunctionCase < M , A extends M , R , N , B extends N , R2 > implements MatchCase < A | B , R | R2 > , PartialMatchCase < A | B , R | R2 > { constructor ( private readonly tailCases , private readonly headCase ) { } partMap ( val , def ) { return this . tailCases . partMap ( val , ( ) : R | R2 => { return this . headCase . partMap ( val , def ) ; } ) ; } /**
     * When called directly on DisjunctionCase - will throw an error if input value not covered
     */ map ( val ) { return this . partMap ( val , ( ) => { throw new Error ( "No match" ) ; } ) ; } caseWhen < U , C extends U , R3 > ( match , handle ) { return new DisjunctionCase < M | N , A | B , R | R2 , U , C , R3 > ( this , new SingleCase ( match , handle ) ) ; } caseDefault < R3 > ( def ) { return new DefaultCase < R | R2 | R3 > ( this , def ) ; } } /**
 * Last case in a chain of cases (default)
 */ export class DefaultCase < R > implements MatchCase < unknown , R > { constructor ( private readonly tailCase , private readonly def ) { } map ( val ) { return this . tailCase . partMap ( val , this . def ) ; } } /**
 * Case always evaluates to given expression result
 */ export class EvalCase < R > implements MatchCase < unknown , R > { constructor ( private readonly val ) { } map ( val ) { return this . val ( ) ; } } param match param map export function caseWhen < M , A extends M , R > ( match , map ) { return new SingleCase ( match , map ) ; } param val export function caseDefault < R > ( val ) { return new EvalCase ( val ) ; } param val param cases export function match < I extends C , C , R > ( val , cases ) { return cases . map ( val ) ; } param cases export function matcher < I extends C , C , R > ( cases ) { return val => cases . map ( val ) ; }