Creating Pattern
There are two types of patterns:
- matchers - they are passed as instance or class constructor as expectation(
Integer,Void,Never,Anyetc..). - containers - they require additional expectation(s) to be passed as arguments on construction(
Tuple,OneOf,Optional,List,Collectionetc...).
Creating matcher
For this example were going to create pattern that matches only positive numbers.
- As first step, we need to create a new pattern that implements
Patterninterface:
Provided kind string returned by getKind() method will inform typend which PatternValidator should be used to validate the value. This significantly improves performance since selection of validator does not need to be evaluated.
In this example typend will search for validator that is registered for kind - positiveNumber.
- Second step requires us to create dedicated validator matching
PatternValidatorinterface:
First lets import all things that will be needed to finish this pattern :
Second were going to focus on pattern evaluation:
This ensures, that only PositiveNumber instance as expectations can used on value validation.
Next, validate method needs to be implemented.
We ensure that provided value is indeed a number type or throw InvalidTypeError. Also we ensure that provided number is not less then 1 or throw InvalidValueError.
We always return true on end of the validation function.
- As third step, we need to wire up our new
PositiveNumberpattern andPositiveNumberValidatorvalidator on typend. To do that we use:
Congratulations, you created new matching pattern!
Since Typend allows matcher patterns to be passed in TypeScript declarations, you are now able to use your matcher like:
You can reassign PositiveNumber to other, lowercased variable if you like to mimic TypeScript's notation:
Or you can use it in JavaScript API like:
Creating container
For this example were going to simplify Optional pattern already included in Typend
- As first step, we need to create a new pattern that implements
.Patterninterface:
Were extending here WrapperPattern, since its much easier to debug complex, multi-level structures that are displayed in console.log like:
For internal workings go to
WrapperPatterncomponent source code
- Second step requires us to create dedicated validator matching
PatternValidatorinterface.
Lets import necessary components:
Again, we'll be first focusing on pattern evaluation:
This time were ensuring, that only Optional pattern expectation can be used to validate related values.
Next, validate method needs to be implemented.
We ensure, that value of any type can be validated, however accept only Optional expectations. Also, this time we pass third parameter to the function validator that on validation will be assigned to Validator implementation.
Since we expect(allow) values to be undefined - we ensure that undefined always return true:
However, if value is assigned - we ensure that it's indeed matching the provided expectation (like new Optional(String) will require value to be undefined or instance of String).
We don't need to re-implement whole validation logic related to each type of validation - just pipe-through the enclosed expectation back to the validator:
This simplifies the validation logic by a lot and enforces consistent results.
- Third step like before is wiring. We need to wire up our new
Optionalpattern andOptionalValidatorvalidator to typend. To do that we use:
However since Typend already has a existing validator for optional kind were going to get error:
Validator for type 'optional' would be overwritten. To override existing validator use 'Validator::overrideValidator'
We need to explicitly override existing one:
Congratulations, you created new container pattern!
To use it you just type: