Creating Pattern
There are two types of patterns:
- matchers - they are passed as instance or class constructor as expectation(
Integer
,Void
,Never
,Any
etc..). - containers - they require additional expectation(s) to be passed as arguments on construction(
Tuple
,OneOf
,Optional
,List
,Collection
etc...).
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
Pattern
interface:
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
PatternValidator
interface:
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
PositiveNumber
pattern andPositiveNumberValidator
validator 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
.Pattern
interface:
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
WrapperPattern
component source code
- Second step requires us to create dedicated validator matching
PatternValidator
interface.
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
Optional
pattern andOptionalValidator
validator 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: