export type Fun < a , b > = ( _ : a ) => b ; export type ListUpperBound < a , b > = b extends a ? b : a extends b ? a : never ; export type ListLowerBound < a , b > = any extends a ? never : a extends b ? never : a ; export type Pattern < a > = a extends number ? a | NumberConstructor : a extends string ? a | StringConstructor : a extends boolean ? a | BooleanConstructor : a extends Array < infer aa > ? [ Pattern < aa > ] : { [ k in keyof a ] ? : Pattern < a [ k ] > ; } ; export type InvertPattern < p > = p extends NumberConstructor ? number : p extends StringConstructor ? string : p extends BooleanConstructor ? boolean : p extends Array < infer pp > ? InvertPattern < pp > [ ] : { [ k in keyof p ] : InvertPattern < p [ k ] > ; } ; param value param otherwise param patterns export const match = < a , b > ( value ) => builder < a , b > ( value ) ( ( ) => undefined , [ ] ) ; const builder = < a , b > ( value ) => ( otherwise = ( ) => null , patterns = [ ] ) => ( { param pattern param expr with : < p extends Pattern < a > > ( pattern , expr ) => builder ( value ) ( otherwise , [ ... patterns , [ pattern , ( ) => true , expr , 'default' ] ] ) , param pattern param when param expr withWhen : < p extends Pattern < a > > ( pattern , when , expr ) => builder ( value ) ( otherwise , [ ... patterns , [ pattern , when , expr , 'default' ] ] ) , param pattern param expr withNot : < p extends Pattern < a > > ( pattern , expr ) => builder ( value ) ( otherwise , [ ... patterns , [ pattern , ( ) => true , expr , 'negated' ] ] ) , param pattern param when param expr withNotWhen : < p extends Pattern < a > > ( pattern , when , expr ) => builder ( value ) ( otherwise , [ ... patterns , [ pattern , when , expr , 'negated' ] ] ) , param otherwise otherwise : ( otherwise ) => builder ( value ) ( otherwise , patterns ) , /**
     * Runs the match and return the result of the first matching pattern
     */ run : ( ) : b => { const p = patterns . find ( p => { if ( p [ 1 ] ( value ) == false ) return false ; if ( p [ 3 ] == 'default' ) return match_pattern ( value , p [ 0 ] ) ; return ! match_pattern ( value , p [ 0 ] ) ; } ) ; if ( p == undefined ) return otherwise ( ) ; return p [ 2 ] ( value ) ; } } ) ; const match_pattern = < a > ( value , pattern ) => { if ( pattern === String ) return typeof ( value ) == 'string' ; if ( pattern === Boolean ) return typeof ( value ) == 'boolean' ; if ( pattern === Number ) return typeof ( value ) == 'number' && Number . isNaN ( value ) == false ; if ( Array . isArray ( pattern ) ) { if ( ! Array . isArray ( value ) ) return false ; return value . every ( v => match_pattern ( v , pattern [ 0 ] ) ) ; } if ( typeof ( value ) != 'object' ) return value === pattern ; return Object . keys ( pattern ) . every ( k => pattern [ k ] == undefined ? false : match_pattern ( value [ k ] , pattern [ k ] ) ) ; } ;