ts-pattern
Advanced tools
Comparing version 0.0.2 to 0.0.3
@@ -19,3 +19,3 @@ /** | ||
/** | ||
* ## Invert Pattern | ||
* ## InvertPattern | ||
* Since patterns have special wildcard values, we need a way | ||
@@ -27,3 +27,2 @@ * to transform a pattern into the type of value it represents | ||
}; | ||
declare type Fun<a, b> = (value: a) => b; | ||
/** | ||
@@ -42,25 +41,16 @@ * ## LeastUpperBound | ||
* Entry point to create pattern matching code branches. It returns an | ||
* empty builder | ||
* empty Match case. | ||
*/ | ||
export declare const match: <a, b>(value: a) => { | ||
with: <p extends Pattern<a>>(pattern: p, f: Fun<LeastUpperBound<a, InvertPattern<p>>, b>) => Match<a, b>; | ||
when: (predicate: Fun<a, unknown>, f: Fun<a, b>) => Match<a, b>; | ||
withWhen: <p_1 extends Pattern<a>>(pattern: p_1, predicate: Fun<LeastUpperBound<a, InvertPattern<p_1>>, unknown>, f: Fun<LeastUpperBound<a, InvertPattern<p_1>>, b>) => Match<a, b>; | ||
otherwise: (f: () => b) => Match<a, b>; | ||
run: () => b; | ||
}; | ||
export declare const match: <a, b>(value: a) => Match<a, b>; | ||
/** | ||
* ## builder | ||
* This is the implementation of our pattern matching, using the | ||
* builder pattern. | ||
* This builder pattern is neat because we can have complexe type checking | ||
* for each of the methods adding new behavior to our pattern matching. | ||
* ## Match | ||
* An interface to create a pattern matching close. | ||
*/ | ||
declare type Match<a, b> = { | ||
with: <p extends Pattern<a>>(pattern: p, f: Fun<MatchedValue<a, p>, b>) => Match<a, b>; | ||
when: (predicate: Fun<a, unknown>, f: Fun<a, b>) => Match<a, b>; | ||
withWhen: <p extends Pattern<a>>(pattern: p, predicate: Fun<MatchedValue<a, p>, unknown>, f: Fun<MatchedValue<a, p>, b>) => Match<a, b>; | ||
otherwise: (f: () => b) => Match<a, b>; | ||
with: <p extends Pattern<a>>(pattern: p, handler: (value: MatchedValue<a, p>) => b) => Match<a, b>; | ||
when: (predicate: (value: a) => unknown, handler: (value: a) => b) => Match<a, b>; | ||
withWhen: <p extends Pattern<a>>(pattern: p, predicate: (value: MatchedValue<a, p>) => unknown, handler: (value: MatchedValue<a, p>) => b) => Match<a, b>; | ||
otherwise: (handler: () => b) => Match<a, b>; | ||
run: () => b; | ||
}; | ||
export {}; |
@@ -31,21 +31,26 @@ "use strict"; | ||
* Entry point to create pattern matching code branches. It returns an | ||
* empty builder | ||
* empty Match case. | ||
*/ | ||
exports.match = function (value) { return builder(value, []); }; | ||
/** | ||
* ## builder | ||
* This is the implementation of our pattern matching, using the | ||
* builder pattern. | ||
* This builder pattern is neat because we can have complexe type checking | ||
* for each of the methods adding new behavior to our pattern matching. | ||
*/ | ||
var builder = function (value, patterns) { return ({ | ||
"with": function (pattern, f) { | ||
return builder(value, __spread(patterns, [[matchPattern(pattern), f]])); | ||
"with": function (pattern, handler) { | ||
return builder(value, __spread(patterns, [[matchPattern(pattern), handler]])); | ||
}, | ||
when: function (predicate, f) { | ||
return builder(value, __spread(patterns, [[predicate, f]])); | ||
}, | ||
withWhen: function (pattern, predicate, f) { | ||
when: function (predicate, handler) { return builder(value, __spread(patterns, [[predicate, handler]])); }, | ||
withWhen: function (pattern, predicate, handler) { | ||
var doesMatch = function (value) { | ||
return Boolean(matchPattern(pattern)(value) && predicate(value)); | ||
}; | ||
return builder(value, __spread(patterns, [[doesMatch, f]])); | ||
return builder(value, __spread(patterns, [[doesMatch, handler]])); | ||
}, | ||
otherwise: function (f) { | ||
otherwise: function (handler) { | ||
return builder(value, __spread(patterns, [ | ||
[matchPattern(exports.__), f], | ||
[matchPattern(exports.__), handler], | ||
])); | ||
@@ -84,3 +89,3 @@ }, | ||
return pattern.length === 1 | ||
? value.every(function (v, i) { return matchPattern(pattern[0])(v); }) | ||
? value.every(function (v) { return matchPattern(pattern[0])(v); }) | ||
: pattern.length === value.length | ||
@@ -87,0 +92,0 @@ ? value.every(function (v, i) { |
{ | ||
"name": "ts-pattern", | ||
"version": "0.0.2", | ||
"version": "0.0.3", | ||
"description": "Typescript pattern matching library", | ||
@@ -9,3 +9,3 @@ "main": "lib/index.js", | ||
"build": "tsc -d", | ||
"prepare": "npm run clean && npm run build", | ||
"prepare": "npm run test && npm run clean && npm run build", | ||
"test": "jest" | ||
@@ -12,0 +12,0 @@ }, |
@@ -1,1 +0,9 @@ | ||
# Match | ||
# Typescript Pattern | ||
A complete pattern matching library for typescript. | ||
### Roadmap | ||
- [ ] Narrow down to type of value in `when` if the predicate is a type guard. | ||
- [ ] Should we remove `run`, and use `otherwise` instead to run the computation ? | ||
- [ ] Find a way to enforce exhaustive pattern matching |
@@ -40,3 +40,3 @@ /** | ||
/** | ||
* ## Invert Pattern | ||
* ## InvertPattern | ||
* Since patterns have special wildcard values, we need a way | ||
@@ -75,5 +75,2 @@ * to transform a pattern into the type of value it represents | ||
// A simple helper to avoid the boilerplate | ||
type Fun<a, b> = (value: a) => b; | ||
/** | ||
@@ -139,55 +136,70 @@ * ## LeastUpperBound | ||
* Entry point to create pattern matching code branches. It returns an | ||
* empty builder | ||
* empty Match case. | ||
*/ | ||
export const match = <a, b>(value: a) => builder<a, b>(value, []); | ||
export const match = <a, b>(value: a): Match<a, b> => builder<a, b>(value, []); | ||
/** | ||
* ## builder | ||
* This is the implementation of our pattern matching, using the | ||
* builder pattern. | ||
* This builder pattern is neat because we can have complexe type checking | ||
* for each of the methods adding new behavior to our pattern matching. | ||
* ## Match | ||
* An interface to create a pattern matching close. | ||
*/ | ||
type Match<a, b> = { | ||
// If the data matches the given pattern, use this branch. | ||
with: <p extends Pattern<a>>( | ||
pattern: p, | ||
f: Fun<MatchedValue<a, p>, b> | ||
handler: (value: MatchedValue<a, p>) => b | ||
) => Match<a, b>; | ||
when: (predicate: Fun<a, unknown>, f: Fun<a, b>) => Match<a, b>; | ||
// When the first function returns a truthy value, use this branch. | ||
when: ( | ||
predicate: (value: a) => unknown, | ||
handler: (value: a) => b | ||
) => Match<a, b>; | ||
// When the data matches the given pattern, and the predicate | ||
// function returns a truthy value, use this branch. | ||
withWhen: <p extends Pattern<a>>( | ||
pattern: p, | ||
predicate: Fun<MatchedValue<a, p>, unknown>, | ||
f: Fun<MatchedValue<a, p>, b> | ||
predicate: (value: MatchedValue<a, p>) => unknown, | ||
handler: (value: MatchedValue<a, p>) => b | ||
) => Match<a, b>; | ||
otherwise: (f: () => b) => Match<a, b>; | ||
// Catch all branch. | ||
otherwise: (handler: () => b) => Match<a, b>; | ||
// Run the pattern matching and return a value. | ||
run: () => b; | ||
}; | ||
/** | ||
* ## builder | ||
* This is the implementation of our pattern matching, using the | ||
* builder pattern. | ||
* This builder pattern is neat because we can have complexe type checking | ||
* for each of the methods adding new behavior to our pattern matching. | ||
*/ | ||
const builder = <a, b>( | ||
value: a, | ||
patterns: [Fun<a, unknown>, Fun<any, b>][] | ||
) => ({ | ||
patterns: [(value: a) => unknown, (value: any) => b][] | ||
): Match<a, b> => ({ | ||
with: <p extends Pattern<a>>( | ||
pattern: p, | ||
f: Fun<MatchedValue<a, p>, b> | ||
handler: (value: MatchedValue<a, p>) => b | ||
): Match<a, b> => | ||
builder<a, b>(value, [...patterns, [matchPattern<a, p>(pattern), f]]), | ||
builder<a, b>(value, [...patterns, [matchPattern<a, p>(pattern), handler]]), | ||
when: (predicate: Fun<a, unknown>, f: Fun<a, b>): Match<a, b> => | ||
builder<a, b>(value, [...patterns, [predicate, f]]), | ||
when: ( | ||
predicate: (value: a) => unknown, | ||
handler: (value: a) => b | ||
): Match<a, b> => builder<a, b>(value, [...patterns, [predicate, handler]]), | ||
withWhen: <p extends Pattern<a>>( | ||
pattern: p, | ||
predicate: Fun<MatchedValue<a, p>, unknown>, | ||
f: Fun<MatchedValue<a, p>, b> | ||
predicate: (value: MatchedValue<a, p>) => unknown, | ||
handler: (value: MatchedValue<a, p>) => b | ||
): Match<a, b> => { | ||
const doesMatch = (value: a) => | ||
Boolean(matchPattern<a, p>(pattern)(value) && predicate(value as any)); | ||
return builder<a, b>(value, [...patterns, [doesMatch, f]]); | ||
return builder<a, b>(value, [...patterns, [doesMatch, handler]]); | ||
}, | ||
otherwise: (f: () => b): Match<a, b> => | ||
otherwise: (handler: () => b): Match<a, b> => | ||
builder<a, b>(value, [ | ||
...patterns, | ||
[matchPattern<a, Pattern<a>>(__ as Pattern<a>), f], | ||
[matchPattern<a, Pattern<a>>(__ as Pattern<a>), handler], | ||
]), | ||
@@ -227,3 +239,3 @@ | ||
return pattern.length === 1 | ||
? value.every((v, i) => matchPattern(pattern[0])(v)) | ||
? value.every((v) => matchPattern(pattern[0])(v)) | ||
: pattern.length === value.length | ||
@@ -230,0 +242,0 @@ ? value.every((v, i) => |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
30261
818
10