Home Reference Source Test

src/pattern-matching/ObjectMatcher.ts

import { TinyType } from '../TinyType';
import { ConstructorAbstractOrInstance } from '../types';
import { PatternMatcher } from './PatternMatcher';
import { MatcherRule, MatchesEqualTinyType, MatchesIdentical, MatchesObjectsWithCommonPrototype } from './rules';

/**
 * @access private
 */
export class ObjectMatcher<Input_Type, Output_Type> extends PatternMatcher<Input_Type, TinyType | ConstructorAbstractOrInstance<Input_Type>, TinyType | Input_Type, Output_Type> {

    when<MT extends Input_Type>(pattern: ConstructorAbstractOrInstance<MT>, transformation: (v: MT) => Output_Type): ObjectMatcher<Input_Type, Output_Type>;
    when(pattern: TinyType, transformation: (v: TinyType) => Output_Type): ObjectMatcher<Input_Type, Output_Type>;
    when(pattern: Input_Type, transformation: (v: Input_Type) => Output_Type): ObjectMatcher<Input_Type, Output_Type>;
    when(pattern: any, transformation: (v: any) => Output_Type) {   // eslint-disable-line @typescript-eslint/explicit-module-boundary-types
        return new ObjectMatcher(
            this.value,
            this.rules.concat(this.rule(pattern, transformation)),
        );
    }

    private rule(pattern: any, transformation: (v: any) => Output_Type): MatcherRule<any, Output_Type> {
        switch (true) {
            case pattern instanceof TinyType:
                return new MatchesEqualTinyType<Output_Type>(pattern as TinyType, transformation);
            case typeof pattern === 'function':
                return new MatchesObjectsWithCommonPrototype<any, Output_Type>(pattern, transformation);
            default:
                return new MatchesIdentical<Input_Type, Output_Type>(pattern, transformation);
        }
    }
}