@eveble/matchist
v1.3.0
Published
Pattern matcher for matching the types and structure of variables
Downloads
17
Readme
Eveble Matchist
Pattern matcher useful for matching types and structure of variables.
Table of Contents
Installation
Using yarn:
yarn install @eveble/matchist
Usage
In Node.js:
Import the library
// Cherry-pick methods for smaller bundles(like rollup).
import {
match,
isMatching,
any,
integer,
objectIncluding,
maybe,
optional,
oneOf,
where,
MatchError,
InvalidDefinitionError,
} from '@eveble/matchist';
Simple definitions
You can define patterns by simply specifying required value type or expected content:
Type
match(null, null); // true
match(undefined, undefined); // true
match('foo', String); // true
match(1, Number); // true
match(true, Boolean); // true
match(new Date('December 17, 1995 03:24:00'), Date); // true
match(/foo/, RegExp); // true
match(() => {
return 'foo';
}, Function); // true
match(['foo', 1, true], Array); // true
match(['foo'], [String]); // true
match(['foo', 1], [String, Number]); // true
match({ foo: 'bar' }, Object); // true
match({ foo: 'bar' }, { foo: String }); // true
match({ foo: 'bar', baz: 1 }, { foo: String, baz: Number }); // true
class FooClass {}
match(new FooClass(), FooClass); // true
match([new FooClass()], [FooClass]); // true
match({ foo: new FooClass() }, { foo: FooClass }); // true
Equality
match('foo', 'foo'); // true
match(1, 1); // true
match(true, true); // true
match(
new Date('December 17, 1995 03:24:00'),
new Date('December 17, 1995 03:24:00')
); // true
match('foo', /foo/); // true
match(['foo'], ['foo']); // true
match(['foo', 1], ['foo', 1]); // true
match(['foo', 'bar'], ['foo', 'bar']); // true
match({ foo: 'bar', baz: 1 }, { foo: 'bar', baz: 1 }); // true
Simple Patterns
The following patterns can be used to alter or augment definitions while still keeping api simple and easily readable. Please be aware you provide invalid definition for pattern - InvalidDefinitionError
will be thrown with detailed
information what type of argument is expected.
any
Matches any value.
match(1, any); // true
match('foo', any); // true
match(new Date(), any); // true
match(true, any); // true
match(false, any); // true
match(undefined, any); // true
match(null, any); // true
match(() => {}, any); // true
match([1, 'foo', true, false], [any]); // true
match({ foo: 'bar' }, { foo: any }); // true
match({ foo: 1 }, { foo: any }); // true
Integer
Matches a signed 32-bit integer. Doesn’t match Infinity
, -Infinity
, NaN
.
match(1, Integer);
match(0, Integer);
match(-1, Integer);
match(-2147483648, Integer);
match(2147483647, Integer);
match(Infinity, Integer); // MatchError: Expected Integer, got Number(null)
match(1.2, Integer); // MatchError: Expected Integer, got Number(1.2)
match('foo', Integer); // MatchError: Expected Integer, got String("foo")
objectIncluding
Matches an Object with the given keys; the value may also have other keys with arbitrary values.
class FooClass {}
match({ foo: 'foo' }, objectIncluding({ foo: String })); // true
match({ foo: new FooClass() }, objectIncluding({ foo: FooClass })); // true
match({ foo: 'foo', bar: 'bar' }, objectIncluding({ foo: String })); // true
match({ foo: 'foo', bar: 'bar' }, objectIncluding({ baz: String })); // MatchError: (Key baz in {"foo":"foo","bar":"bar"}) - Expected undefined to be a String
maybe
Matches: undefined
, null
or provided pattern. When used on Object
it matches only if the key is not set as opposed to the value being set to undefined
or null
.
match(undefined, maybe(String)); // true
match(null, maybe(String)); // true
match({ required: 'value' }, { required: String, maybe: maybe(String) }); // true
match(
{ required: 'value', maybe: undefined },
{ required: String, maybe: maybe(String) }
); // true
match(
{ required: 'value', maybe: null },
{ required: String, maybe: maybe(String) }
); // true
optional
Matches: undefined
or provided pattern. When used in an Object
, the behavior is identical to maybe
.
match(undefined, optional(String));
match(null, optional(String)); // MatchError: Expected null to be a String
match({ required: 'value' }, { required: String, optional: optional(String) }); // true
match(
{ required: 'value', optional: undefined },
{ required: String, optional: optional(String) }
); // true
match(
{ required: 'value', optional: null },
{ required: String, optional: optional(String) }
); // MatchError: (Key optional in {"required":"value","optional":null}) - Expected null to be a String
oneOf
Matches any value that is a valid match for one of the provided arguments(patterns).
match({ foo: new MyClass() }, objectIncluding({ foo: MyClass })); // true
match('foo', oneOf(String, Number)); // true
match(10, oneOf(String, Number)); // true
match([1, 2, 3], oneOf([String], [Number])); // true
match(['foo', 'bar'], oneOf([String], [Number])); // true
match(1, oneOf(1, 2)); // true
match(new Date('December 17, 1995 03:24:00'), oneOf(String, Date)); // true
match('foo', oneOf('foo', 'bar')); // true
match('qux', oneOf('foo', 'bar')); // MatchError: Expected String("qux") to be one of: String("foo"), String("bar")
match(null, oneOf(null, undefined)); // true
match(undefined, oneOf(null, undefined)); // true
match(true, oneOf(true, false)); // true
match(false, oneOf(true, false)); // true
match(new MyClass(), oneOf(String, MyClass)); // true
match(MyClass, oneOf(String, MyClass)); // true
match('foo', oneOf('foo', 'bar')); // true
match('foo', oneOf('bar', /^foo$/g)); // true
match({ foo: 'bar' }, { foo: oneOf('bar', 'baz') }); // true
match({ foo: 'baz' }, { foo: oneOf('bar', 'baz') }); // true
match({ foo: 'qux' }, { foo: oneOf('bar', 'baz') }); // MatchError: (Key foo in {"foo":"qux"}) - Expected String("qux") to be one of: String("bar"), String("baz")
where
Calls the function with the value as the argument. If returns true
, this match is valid. If condition throws a MatchError
or returns false, this fails.
match(
'foo',
where(value => {
return value === 'foo';
})
); // true
match(
'not-foo',
where(value => {
return value === 'foo';
})
); // Failed WherePattern validation
match(
`Luke, I'm your father!`,
where(value => {
const isValid = value === `Luke, I'm your father!`;
if (!isValid) {
throw new MatchError(`nooooooooo!`);
}
return isValid;
})
); // MatchError: nooooooooo!
match(
{ foo: 'foo' },
{
foo: where(value => {
return value === 'foo';
}),
}
); // true
Explicit Patterns
instanceOf
Matches if provided value is instance of specific type.
match(null, instanceOf(null)); // true
match(undefined, instanceOf(undefined)); // true
match('foo', instanceOf(String)); // true
match(1, instanceOf(Number)); // true
match(true, instanceOf(Boolean)); // true
match(new Date('December 17, 1995 03:24:00'), instanceOf(Date)); // true
match(/foo/, instanceOf(RegExp)); // true
match(() => {
return 'foo';
}, instanceOf(Function)); // true
match(['foo'], instanceOf(Array)); // true
match({ foo: 'bar' }, instanceOf(Object)); // true
equals
Matches value content(for Array use ArrayPattern
, for Objects use ObjectPattern
or just use simple pattern definition(implicit) - otherwise MatchError
will be thrown).
match('foo', equals('foo')); // true
match(1, equals(1)); // true
match(true, equals(true)); // true
match(
new Date('December 17, 1995 03:24:00'),
equals(new Date('December 17, 1995 03:24:00'))
); // true
match('foo', equals(/foo/)); // true
ArrayPattern
Matches value patterns inside Array.
match(['foo', 1, true], new ArrayPattern(Array)); // true
match(['foo'], new ArrayPattern([String])); // true
match(['foo', 1], new ArrayPattern([String, Number])); // true
match(['foo'], new ArrayPattern(['foo'])); // true
match(['foo', 1], new ArrayPattern(['foo', 1])); // true
ObjectPattern
Matches key:value pairs inside Object.
match({ foo: 'bar' }, new ObjectPattern({ foo: String })); // true
match({ foo: 'bar', baz: 1 }, new ObjectPattern({ foo: String, baz: Number })); // true
match(
{ foo: 'bar', baz: 'qux' },
new ObjectPattern({ foo: 'bar', baz: 'qux' })
); // true
You can always use instantiation way to define patterns instead of using simple api:
| Simple API | Instantiation API |
| ------------------- | ------------------------------ |
| any()
| new AnythingPattern()
|
| equals()
| new EqualityPattern()
|
| Integer()
| new IntegerPattern()
|
| objectIncluding()
| new ObjectIncludingPattern()
|
| oneOf()
| new OneOfPattern()
|
| maybe()
| new MaybePattern()
|
| optional()
| new OptionalPattern()
|
| instanceOf()
| new TypePattern()
|
| where()
| new WherePattern()
|
API
Package supports two ways of validating values:
match
match
will return true upon value matching pattern or throw MatchError
with human readable error message that can be shown back to the user.
match(value, patternOrDef, isStrict); // true or throws MatchError
import { match } from '@eveble/matchist';
| ARGUMENTS | | |
| --------------- | ------------ | -------------------------------------------------------------------- |
| value | Any | The value to check |
| patternOrDef | Pattern|Any | The Pattern
instance or implicit definition to match value against |
| [isStrict=true] | Boolean | Flag indicating that evaluation should be done in strict mode. |
isMatching
isMatching
will return boolean on successful or failed matching pattern.
isMatching(value, pattern, isStrict); // true or false
import { isMatching } from '@eveble/matchist';
| ARGUMENTS | | |
| --------------- | ------------ | -------------------------------------------------------------------- |
| value | Any | The value to check |
| patternOrDef | Pattern|Any | The Pattern
instance or implicit definition to match value against |
| [isStrict=true] | Boolean | Flag indicating that evaluation should be done in strict mode. |
Testing
Using yarn:
yarn test
License
The MIT License (MIT)
Copyright (c)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.