@@ -3,6 +3,15 @@ import { Match } from './types/Match';
33import * as symbols from './internals/symbols' ;
44import { matchPattern } from './internals/helpers' ;
55
6+ type MatchState < output > =
7+ | { matched : true ; value : output }
8+ | { matched : false ; value : undefined } ;
9+
10+ const unmatched : MatchState < never > = {
11+ matched : false ,
12+ value : undefined ,
13+ } ;
14+
615/**
716 * `match` creates a **pattern matching expression**.
817 * * Use `.with(pattern, handler)` to pattern match on the input.
@@ -22,18 +31,9 @@ import { matchPattern } from './internals/helpers';
2231export function match < const input , output = symbols . unset > (
2332 value : input
2433) : Match < input , output > {
25- return new MatchExpression ( value ) as any ;
34+ return new MatchExpression ( value , unmatched ) as any ;
2635}
2736
28- type MatchState < output > =
29- | { matched : true ; value : output }
30- | { matched : false ; value : undefined } ;
31-
32- const unmatched : MatchState < never > = {
33- matched : false ,
34- value : undefined ,
35- } ;
36-
3737/**
3838 * This class represents a match expression. It follows the
3939 * builder pattern, we chain methods to add features to the expression
@@ -44,10 +44,7 @@ const unmatched: MatchState<never> = {
4444 * can be found in src/types/Match.ts.
4545 */
4646class MatchExpression < input , output > {
47- constructor (
48- private input : input ,
49- private state : MatchState < output > = unmatched
50- ) { }
47+ constructor ( private input : input , private state : MatchState < output > ) { }
5148
5249 with ( ...args : any [ ] ) : MatchExpression < input , output > {
5350 if ( this . state . matched ) return this ;
@@ -56,38 +53,38 @@ class MatchExpression<input, output> {
5653 args [ args . length - 1 ] ;
5754
5855 const patterns : Pattern < input > [ ] = [ args [ 0 ] ] ;
59- const predicates : ( ( value : input ) => unknown ) [ ] = [ ] ;
56+ let predicate : ( ( value : input ) => unknown ) | undefined = undefined ;
6057
61- // case with guard as second argument
6258 if ( args . length === 3 && typeof args [ 1 ] === 'function' ) {
59+ // case with guard as second argument
6360 patterns . push ( args [ 0 ] ) ;
64- predicates . push ( args [ 1 ] ) ;
61+ predicate = args [ 1 ] ;
6562 } else if ( args . length > 2 ) {
6663 // case with several patterns
6764 patterns . push ( ...args . slice ( 1 , args . length - 1 ) ) ;
6865 }
6966
67+ let hasSelections = false ;
7068 let selected : Record < string , unknown > = { } ;
69+ const select = ( key : string , value : unknown ) => {
70+ hasSelections = true ;
71+ selected [ key ] = value ;
72+ } ;
7173
72- const matched = Boolean (
73- patterns . some ( ( pattern ) =>
74- matchPattern ( pattern , this . input , ( key , value ) => {
75- selected [ key ] = value ;
76- } )
77- ) && predicates . every ( ( predicate ) => predicate ( this . input ) )
78- ) ;
74+ const matched =
75+ patterns . some ( ( pattern ) => matchPattern ( pattern , this . input , select ) ) &&
76+ ( predicate ? Boolean ( predicate ( this . input ) ) : true ) ;
77+
78+ const selections = hasSelections
79+ ? symbols . anonymousSelectKey in selected
80+ ? selected [ symbols . anonymousSelectKey ]
81+ : selected
82+ : this . input ;
7983
8084 const state = matched
8185 ? {
8286 matched : true as const ,
83- value : handler (
84- Object . keys ( selected ) . length
85- ? symbols . anonymousSelectKey in selected
86- ? selected [ symbols . anonymousSelectKey ]
87- : selected
88- : this . input ,
89- this . input
90- ) ,
87+ value : handler ( selections , this . input ) ,
9188 }
9289 : unmatched ;
9390
0 commit comments