Socket
Socket
Sign inDemoInstall

ts-pattern

Package Overview
Dependencies
Maintainers
1
Versions
151
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ts-pattern - npm Package Compare versions

Comparing version 0.1.2 to 0.1.3

66

lib/index.d.ts
/**
* # Pattern matching
**/
declare enum PatternType {
String = "@match/string",
Number = "@match/number",
Boolean = "@match/boolean",
Guard = "@match/guard",
Not = "@match/not"
}
/**
* GuardValue returns the value guarded by a type guard function.
* ### Catch All wildcard
* `__` refers to a wildcard pattern, matching any value
*/
declare type GuardValue<F> = F extends (value: any) => value is infer b ? b : F extends (value: infer a) => unknown ? a : never;
export declare const __: {
readonly string: PatternType.String;
readonly number: PatternType.Number;
readonly boolean: PatternType.Boolean;
};
/** type alias for the catch all string */
declare type __ = '__CATCH_ALL__';
declare type __ = typeof __;
declare type Primitives = number | boolean | string | undefined | null | symbol | bigint;
/**
* ### Catch All wildcard
* `__` refers to a wildcard pattern, matching any value
* GuardValue returns the value guarded by a type guard function.
*/
export declare const __: __;
declare type GuardValue<F> = F extends (value: any) => value is infer b ? b : F extends (value: infer a) => unknown ? a : never;
declare type GuardFunction<a> = (value: a) => unknown;
declare type GuardPattern<a> = {
patternKind: PatternType.Guard;
when: GuardFunction<a>;
};
declare type NotPattern<a> = {
patternKind: PatternType.Not;
pattern: Pattern<a>;
};
declare type SpecialPattern<a> = a extends number ? typeof __.number | __ : a extends string ? typeof __.string | __ : a extends boolean ? typeof __.boolean | __ : __;
/**

@@ -20,5 +42,5 @@ * ### Pattern

*/
export declare type Pattern<a> = a extends number ? a | NumberConstructor | __ : a extends string ? a | StringConstructor | __ : a extends boolean ? a | BooleanConstructor | __ : a extends [infer b, infer c, infer d, infer e, infer f] ? [Pattern<b>, Pattern<c>, Pattern<d>, Pattern<e>, Pattern<f>] | __ : a extends [infer b, infer c, infer d, infer e] ? [Pattern<b>, Pattern<c>, Pattern<d>, Pattern<e>] | __ : a extends [infer b, infer c, infer d] ? [Pattern<b>, Pattern<c>, Pattern<d>] | __ : a extends [infer b, infer c] ? [Pattern<b>, Pattern<c>] | __ : a extends (infer b)[] ? Pattern<b>[] | __ : a extends Map<infer k, infer v> ? Map<k, Pattern<v>> | __ : a extends Set<infer v> ? Set<Pattern<v>> | __ : {
export declare type Pattern<a> = GuardPattern<a> | NotPattern<a | any> | SpecialPattern<a> | (a extends Primitives ? a : a extends [infer b, infer c, infer d, infer e, infer f] ? [Pattern<b>, Pattern<c>, Pattern<d>, Pattern<e>, Pattern<f>] : a extends [infer b, infer c, infer d, infer e] ? [Pattern<b>, Pattern<c>, Pattern<d>, Pattern<e>] : a extends [infer b, infer c, infer d] ? [Pattern<b>, Pattern<c>, Pattern<d>] : a extends [infer b, infer c] ? [Pattern<b>, Pattern<c>] : a extends (infer b)[] ? Pattern<b>[] : a extends Map<infer k, infer v> ? Map<k, Pattern<v>> : a extends Set<infer v> ? Set<Pattern<v>> : a extends object ? {
[k in keyof a]?: Pattern<a[k]>;
} | __;
} : a);
/**

@@ -29,5 +51,8 @@ * ### InvertPattern

*/
declare type InvertPattern<p> = p extends NumberConstructor ? number : p extends StringConstructor ? string : p extends BooleanConstructor ? boolean : p extends [infer pb, infer pc, infer pd, infer pe, infer pf] ? [InvertPattern<pb>, InvertPattern<pc>, InvertPattern<pd>, InvertPattern<pe>, InvertPattern<pf>] : p extends [infer pb, infer pc, infer pd, infer pe] ? [InvertPattern<pb>, InvertPattern<pc>, InvertPattern<pd>, InvertPattern<pe>] : p extends [infer pb, infer pc, infer pd] ? [InvertPattern<pb>, InvertPattern<pc>, InvertPattern<pd>] : p extends [infer pb, infer pc] ? [InvertPattern<pb>, InvertPattern<pc>] : p extends (infer pp)[] ? InvertPattern<pp>[] : p extends Map<infer pk, infer pv> ? Map<pk, InvertPattern<pv>> : p extends Set<infer pv> ? Set<InvertPattern<pv>> : p extends __ ? __ : {
declare type InvertPattern<p> = p extends typeof __.number ? number : p extends typeof __.string ? string : p extends typeof __.boolean ? boolean : p extends __ ? __ : p extends GuardPattern<infer pb> ? GuardValue<p['when']> : p extends NotPattern<infer pb> ? {
valueKind: PatternType.Not;
pattern: InvertPattern<pb>;
} : p extends Primitives ? p : p extends [infer pb, infer pc, infer pd, infer pe, infer pf] ? [InvertPattern<pb>, InvertPattern<pc>, InvertPattern<pd>, InvertPattern<pe>, InvertPattern<pf>] : p extends [infer pb, infer pc, infer pd, infer pe] ? [InvertPattern<pb>, InvertPattern<pc>, InvertPattern<pd>, InvertPattern<pe>] : p extends [infer pb, infer pc, infer pd] ? [InvertPattern<pb>, InvertPattern<pc>, InvertPattern<pd>] : p extends [infer pb, infer pc] ? [InvertPattern<pb>, InvertPattern<pc>] : p extends (infer pp)[] ? InvertPattern<pp>[] : p extends Map<infer pk, infer pv> ? Map<pk, InvertPattern<pv>> : p extends Set<infer pv> ? Set<InvertPattern<pv>> : p extends object ? {
[k in keyof p]: InvertPattern<p[k]>;
};
} : p;
/**

@@ -41,5 +66,22 @@ * ### LeastUpperBound

*/
declare type LeastUpperBound<a, b> = [a, b] extends [[infer aa, infer ab, infer ac, infer ad, infer ae], [infer ba, infer bb, infer bc, infer bd, infer be]] ? [LeastUpperBound<aa, ba>, LeastUpperBound<ab, bb>, LeastUpperBound<ac, bc>, LeastUpperBound<ad, bd>, LeastUpperBound<ae, be>] : [a, b] extends [[infer aa, infer ab, infer ac, infer ad], [infer ba, infer bb, infer bc, infer bd]] ? [LeastUpperBound<aa, ba>, LeastUpperBound<ab, bb>, LeastUpperBound<ac, bc>, LeastUpperBound<ad, bd>] : [a, b] extends [[infer aa, infer ab, infer ac], [infer ba, infer bb, infer bc]] ? [LeastUpperBound<aa, ba>, LeastUpperBound<ab, bb>, LeastUpperBound<ac, bc>] : [a, b] extends [[infer aa, infer ab], [infer ba, infer bb]] ? [LeastUpperBound<aa, ba>, LeastUpperBound<ab, bb>] : [a, b] extends [(infer aa)[], (infer ba)[]] ? LeastUpperBound<aa, ba>[] : [a, b] extends [Map<infer ak, infer av>, Map<infer bk, infer bv>] ? Map<LeastUpperBound<ak, bk>, LeastUpperBound<av, bv>> : [a, b] extends [Set<infer av>, Set<infer bv>] ? Set<LeastUpperBound<av, bv>> : b extends __ ? a : a extends __ ? b : b extends a ? b : a extends b ? a : never;
declare type MatchedValue<a, p extends Pattern<a>> = LeastUpperBound<a, InvertPattern<p>>;
declare type LeastUpperBound<a, b> = b extends a ? b : a extends b ? a : never;
declare type ExtractMostPreciseValue<a, b> = [a, b] extends [[infer a1, infer a2, infer a3, infer a4, infer a5], [infer b1, infer b2, infer b3, infer b4, infer b5]] ? [ExtractMostPreciseValue<a1, b1>, ExtractMostPreciseValue<a2, b2>, ExtractMostPreciseValue<a3, b3>, ExtractMostPreciseValue<a4, b4>, ExtractMostPreciseValue<a5, b5>] : [a, b] extends [[infer a1, infer a2, infer a3, infer a4], [infer b1, infer b2, infer b3, infer b4]] ? [ExtractMostPreciseValue<a1, b1>, ExtractMostPreciseValue<a2, b2>, ExtractMostPreciseValue<a3, b3>, ExtractMostPreciseValue<a4, b4>] : [a, b] extends [[infer a1, infer a2, infer a3], [infer b1, infer b2, infer b3]] ? [ExtractMostPreciseValue<a1, b1>, ExtractMostPreciseValue<a2, b2>, ExtractMostPreciseValue<a3, b3>] : [a, b] extends [[infer a1, infer a2], [infer b1, infer b2]] ? [ExtractMostPreciseValue<a1, b1>, ExtractMostPreciseValue<a2, b2>] : [a, b] extends [(infer a1)[], (infer b1)[]] ? ExtractMostPreciseValue<a1, b1>[] : [a, b] extends [Map<infer ak, infer av>, Map<infer bk, infer bv>] ? Map<ExtractMostPreciseValue<ak, bk>, ExtractMostPreciseValue<av, bv>> : [a, b] extends [Set<infer av>, Set<infer bv>] ? Set<ExtractMostPreciseValue<av, bv>> : b extends __ ? a : b extends {
valueKind: PatternType.Not;
pattern: infer b1;
} ? Exclude<a, b1> : [a, b] extends [object, object] ? ObjectExtractMostPreciseValue<a, b> : LeastUpperBound<a, b>;
/**
* if a key of an object has the never type,
* returns never, otherwise returns the type of object
**/
declare type ExcludeIfContainsNever<a> = ValueOf<{
[k in keyof a]: a[k] extends never ? 'exclude' : 'include';
}> extends 'include' ? a : never;
declare type ObjectExtractMostPreciseValue<a, b> = b extends a ? b : a extends b ? a : ExcludeIfContainsNever<{
[k in keyof a]: k extends keyof b ? ExtractMostPreciseValue<a[k], b[k]> : a[k];
}>;
declare type ValueOf<a> = a[keyof a];
declare type MatchedValue<a, p extends Pattern<a>> = ExtractMostPreciseValue<a, InvertPattern<p>>;
export declare const when: <a>(predicate: GuardFunction<a>) => GuardPattern<a>;
export declare const not: <a>(pattern: Pattern<a>) => NotPattern<a>;
/**
* ### match

@@ -46,0 +88,0 @@ * Entry point to create pattern matching code branches. It returns an

@@ -26,3 +26,11 @@ "use strict";

exports.__esModule = true;
exports.match = exports.__ = void 0;
exports.match = exports.not = exports.when = exports.__ = void 0;
var PatternType;
(function (PatternType) {
PatternType["String"] = "@match/string";
PatternType["Number"] = "@match/number";
PatternType["Boolean"] = "@match/boolean";
PatternType["Guard"] = "@match/guard";
PatternType["Not"] = "@match/not";
})(PatternType || (PatternType = {}));
/**

@@ -32,3 +40,15 @@ * ### Catch All wildcard

*/
exports.__ = '__CATCH_ALL__';
exports.__ = {
string: PatternType.String,
number: PatternType.Number,
boolean: PatternType.Boolean
};
exports.when = function (predicate) { return ({
patternKind: PatternType.Guard,
when: predicate
}); };
exports.not = function (pattern) { return ({
patternKind: PatternType.Not,
pattern: pattern
}); };
/**

@@ -78,3 +98,12 @@ * ### match

};
var wildcards = [String, Boolean, Number];
var isGuardPattern = function (x) {
var pattern = x;
return (pattern &&
pattern.patternKind === PatternType.Guard &&
typeof pattern.when === 'function');
};
var isNotPattern = function (x) {
var pattern = x;
return pattern && pattern.patternKind === PatternType.Not;
};
// tells us if the value matches a given pattern.

@@ -84,9 +113,13 @@ var matchPattern = function (pattern) { return function (value) {

return true;
if (pattern === String)
if (pattern === exports.__.string)
return typeof value === 'string';
if (pattern === Boolean)
if (pattern === exports.__.boolean)
return typeof value === 'boolean';
if (pattern === Number) {
if (pattern === exports.__.number) {
return typeof value === 'number' && !Number.isNaN(value);
}
if (isGuardPattern(pattern))
return Boolean(pattern.when(value));
if (isNotPattern(pattern))
return !matchPattern(pattern.pattern)(value);
if (typeof pattern !== typeof value)

@@ -115,3 +148,3 @@ return false;

? patternValues.every(function (subPattern) {
return wildcards.includes(subPattern)
return Object.values(exports.__).includes(subPattern)
? matchPattern([subPattern])(allValues_1)

@@ -118,0 +151,0 @@ : value.has(subPattern);

2

package.json
{
"name": "ts-pattern",
"version": "0.1.2",
"version": "0.1.3",
"description": "Typescript pattern matching library",

@@ -5,0 +5,0 @@ "main": "lib/index.js",

# Typescript Pattern
A complete pattern matching library for typescript.
```ts
import { match, __, when, not } from 'pattern';
match({ type: 'hello' })
.with(__, () => 'ok')
.with(__.string, () => 'ok')
.with(
when((x) => true),
() => 'ok'
)
.with(not('hello'), () => 'ok')
.with(not(__.string), () => 'ok')
.with(not(when((x) => true)), () => 'ok')
.with({ type: __ }, () => 'ok')
.with({ type: __.string }, () => 'ok')
.with({ type: when((x) => true) }, () => 'ok')
.with({ type: not('hello') }, () => 'ok')
.with({ type: not(__.string) }, () => 'ok')
.with({ type: not(when((x) => true)) }, () => 'ok');
```
### Roadmap
- [ ] Forbid impossible patterns like `{ status: 'error', data: (data) => data.length > 3 }` (error have no data)
- [ ] Find a way to enforce exhaustive pattern matching

@@ -4,0 +6,0 @@ - [ ] Add `not(value)` in patterns.

@@ -5,3 +5,33 @@ /**

enum PatternType {
String = '@match/string',
Number = '@match/number',
Boolean = '@match/boolean',
Guard = '@match/guard',
Not = '@match/not',
}
/**
* ### Catch All wildcard
* `__` refers to a wildcard pattern, matching any value
*/
export const __ = {
string: PatternType.String,
number: PatternType.Number,
boolean: PatternType.Boolean,
} as const;
/** type alias for the catch all string */
type __ = typeof __;
type Primitives =
| number
| boolean
| string
| undefined
| null
| symbol
| bigint;
/**
* GuardValue returns the value guarded by a type guard function.

@@ -15,10 +45,22 @@ */

/** type alias for the catch all string */
type __ = '__CATCH_ALL__';
/**
* ### Catch All wildcard
* `__` refers to a wildcard pattern, matching any value
*/
export const __: __ = '__CATCH_ALL__';
type GuardFunction<a> = (value: a) => unknown;
type GuardPattern<a> = {
patternKind: PatternType.Guard;
when: GuardFunction<a>;
};
type NotPattern<a> = {
patternKind: PatternType.Not;
pattern: Pattern<a>;
};
type SpecialPattern<a> = a extends number
? typeof __.number | __
: a extends string
? typeof __.string | __
: a extends boolean
? typeof __.boolean | __
: __;
/**

@@ -29,23 +71,25 @@ * ### Pattern

*/
export type Pattern<a> = a extends number
? a | NumberConstructor | __
: a extends string
? a | StringConstructor | __
: a extends boolean
? a | BooleanConstructor | __
: a extends [infer b, infer c, infer d, infer e, infer f]
? [Pattern<b>, Pattern<c>, Pattern<d>, Pattern<e>, Pattern<f>] | __
: a extends [infer b, infer c, infer d, infer e]
? [Pattern<b>, Pattern<c>, Pattern<d>, Pattern<e>] | __
: a extends [infer b, infer c, infer d]
? [Pattern<b>, Pattern<c>, Pattern<d>] | __
: a extends [infer b, infer c]
? [Pattern<b>, Pattern<c>] | __
: a extends (infer b)[]
? Pattern<b>[] | __
: a extends Map<infer k, infer v>
? Map<k, Pattern<v>> | __
: a extends Set<infer v>
? Set<Pattern<v>> | __
: { [k in keyof a]?: Pattern<a[k]> } | __;
export type Pattern<a> =
| GuardPattern<a>
| NotPattern<a | any>
| SpecialPattern<a>
| (a extends Primitives
? a
: a extends [infer b, infer c, infer d, infer e, infer f]
? [Pattern<b>, Pattern<c>, Pattern<d>, Pattern<e>, Pattern<f>]
: a extends [infer b, infer c, infer d, infer e]
? [Pattern<b>, Pattern<c>, Pattern<d>, Pattern<e>]
: a extends [infer b, infer c, infer d]
? [Pattern<b>, Pattern<c>, Pattern<d>]
: a extends [infer b, infer c]
? [Pattern<b>, Pattern<c>]
: a extends (infer b)[]
? Pattern<b>[]
: a extends Map<infer k, infer v>
? Map<k, Pattern<v>>
: a extends Set<infer v>
? Set<Pattern<v>>
: a extends object
? { [k in keyof a]?: Pattern<a[k]> }
: a);

@@ -57,8 +101,19 @@ /**

*/
type InvertPattern<p> = p extends NumberConstructor
type InvertPattern<p> = p extends typeof __.number
? number
: p extends StringConstructor
: p extends typeof __.string
? string
: p extends BooleanConstructor
: p extends typeof __.boolean
? boolean
: p extends __
? __
: p extends GuardPattern<infer pb>
? GuardValue<p['when']>
: p extends NotPattern<infer pb>
? {
valueKind: PatternType.Not;
pattern: InvertPattern<pb>;
}
: p extends Primitives
? p
: p extends [infer pb, infer pc, infer pd, infer pe, infer pf]

@@ -84,5 +139,5 @@ ? [

? Set<InvertPattern<pv>>
: p extends __
? __
: { [k in keyof p]: InvertPattern<p[k]> };
: p extends object
? { [k in keyof p]: InvertPattern<p[k]> }
: p;

@@ -97,47 +152,78 @@ /**

*/
type LeastUpperBound<a, b> = [a, b] extends [
[infer aa, infer ab, infer ac, infer ad, infer ae],
[infer ba, infer bb, infer bc, infer bd, infer be]
type LeastUpperBound<a, b> = b extends a ? b : a extends b ? a : never;
type ExtractMostPreciseValue<a, b> = [a, b] extends [
[infer a1, infer a2, infer a3, infer a4, infer a5],
[infer b1, infer b2, infer b3, infer b4, infer b5]
] // quintupple
? [
LeastUpperBound<aa, ba>,
LeastUpperBound<ab, bb>,
LeastUpperBound<ac, bc>,
LeastUpperBound<ad, bd>,
LeastUpperBound<ae, be>
ExtractMostPreciseValue<a1, b1>,
ExtractMostPreciseValue<a2, b2>,
ExtractMostPreciseValue<a3, b3>,
ExtractMostPreciseValue<a4, b4>,
ExtractMostPreciseValue<a5, b5>
]
: [a, b] extends [
[infer aa, infer ab, infer ac, infer ad],
[infer ba, infer bb, infer bc, infer bd]
] // quadrupple
[infer a1, infer a2, infer a3, infer a4],
[infer b1, infer b2, infer b3, infer b4]
] // qua4rupple
? [
LeastUpperBound<aa, ba>,
LeastUpperBound<ab, bb>,
LeastUpperBound<ac, bc>,
LeastUpperBound<ad, bd>
ExtractMostPreciseValue<a1, b1>,
ExtractMostPreciseValue<a2, b2>,
ExtractMostPreciseValue<a3, b3>,
ExtractMostPreciseValue<a4, b4>
]
: [a, b] extends [
[infer aa, infer ab, infer ac],
[infer ba, infer bb, infer bc]
[infer a1, infer a2, infer a3],
[infer b1, infer b2, infer b3]
] // tripple
? [LeastUpperBound<aa, ba>, LeastUpperBound<ab, bb>, LeastUpperBound<ac, bc>]
: [a, b] extends [[infer aa, infer ab], [infer ba, infer bb]] // tupple
? [LeastUpperBound<aa, ba>, LeastUpperBound<ab, bb>]
: [a, b] extends [(infer aa)[], (infer ba)[]]
? LeastUpperBound<aa, ba>[]
? [
ExtractMostPreciseValue<a1, b1>,
ExtractMostPreciseValue<a2, b2>,
ExtractMostPreciseValue<a3, b3>
]
: [a, b] extends [[infer a1, infer a2], [infer b1, infer b2]] // tupple
? [ExtractMostPreciseValue<a1, b1>, ExtractMostPreciseValue<a2, b2>]
: [a, b] extends [(infer a1)[], (infer b1)[]]
? ExtractMostPreciseValue<a1, b1>[]
: [a, b] extends [Map<infer ak, infer av>, Map<infer bk, infer bv>]
? Map<LeastUpperBound<ak, bk>, LeastUpperBound<av, bv>>
? Map<ExtractMostPreciseValue<ak, bk>, ExtractMostPreciseValue<av, bv>>
: [a, b] extends [Set<infer av>, Set<infer bv>]
? Set<LeastUpperBound<av, bv>>
? Set<ExtractMostPreciseValue<av, bv>>
: b extends __
? a
: a extends __
: b extends { valueKind: PatternType.Not; pattern: infer b1 }
? Exclude<a, b1>
: [a, b] extends [object, object]
? ObjectExtractMostPreciseValue<a, b>
: LeastUpperBound<a, b>;
/**
* if a key of an object has the never type,
* returns never, otherwise returns the type of object
**/
type ExcludeIfContainsNever<a> = ValueOf<
{
[k in keyof a]: a[k] extends never ? 'exclude' : 'include';
}
> extends 'include'
? a
: never;
type ObjectExtractMostPreciseValue<a, b> = b extends a
? b
: b extends a
? b
: a extends b
? a
: never;
: ExcludeIfContainsNever<
{
[k in keyof a]: k extends keyof b
? ExtractMostPreciseValue<a[k], b[k]>
: a[k];
}
>;
type MatchedValue<a, p extends Pattern<a>> = LeastUpperBound<
type ValueOf<a> = a[keyof a];
type MatchedValue<a, p extends Pattern<a>> = ExtractMostPreciseValue<
a,

@@ -147,2 +233,12 @@ InvertPattern<p>

export const when = <a>(predicate: GuardFunction<a>): GuardPattern<a> => ({
patternKind: PatternType.Guard,
when: predicate,
});
export const not = <a>(pattern: Pattern<a>): NotPattern<a> => ({
patternKind: PatternType.Not,
pattern,
});
/**

@@ -266,4 +362,16 @@ * ### match

const wildcards = [String, Boolean, Number];
const isGuardPattern = (x: unknown): x is GuardPattern<unknown> => {
const pattern = x as GuardPattern<unknown>;
return (
pattern &&
pattern.patternKind === PatternType.Guard &&
typeof pattern.when === 'function'
);
};
const isNotPattern = (x: unknown): x is NotPattern<unknown> => {
const pattern = x as NotPattern<unknown>;
return pattern && pattern.patternKind === PatternType.Not;
};
// tells us if the value matches a given pattern.

@@ -274,7 +382,9 @@ const matchPattern = <a, p extends Pattern<a>>(pattern: p) => (

if (pattern === __) return true;
if (pattern === String) return typeof value === 'string';
if (pattern === Boolean) return typeof value === 'boolean';
if (pattern === Number) {
if (pattern === __.string) return typeof value === 'string';
if (pattern === __.boolean) return typeof value === 'boolean';
if (pattern === __.number) {
return typeof value === 'number' && !Number.isNaN(value);
}
if (isGuardPattern(pattern)) return Boolean(pattern.when(value));
if (isNotPattern(pattern)) return !matchPattern(pattern.pattern)(value);

@@ -306,3 +416,3 @@ if (typeof pattern !== typeof value) return false;

? patternValues.every((subPattern) =>
wildcards.includes(subPattern)
Object.values(__).includes(subPattern)
? matchPattern<any, Pattern<any>>([subPattern])(allValues)

@@ -309,0 +419,0 @@ : value.has(subPattern)

@@ -1,2 +0,2 @@

import { match, __, Pattern } from '../src';
import { match, __, when, not, Pattern } from '../src';

@@ -11,6 +11,6 @@ type Option<a> = { kind: 'none' } | { kind: 'some'; value: a };

type State =
| { status: 'idle'; data?: undefined; error?: undefined }
| { status: 'loading'; data?: undefined; error?: undefined }
| { status: 'success'; data: string; error?: undefined }
| { status: 'error'; data?: undefined; error: Error };
| { status: 'idle' }
| { status: 'loading' }
| { status: 'success'; data: string }
| { status: 'error'; error: Error };

@@ -24,5 +24,5 @@ type Event =

describe('types', () => {
it('Pattern type should typecheck', () => {
type Input = [State, Event];
type Input = [State, Event];
it('wildcard patterns should typecheck', () => {
let pattern: Pattern<Input>;

@@ -32,2 +32,3 @@ pattern = __;

pattern = [{ status: 'success', data: '' }, __];
pattern = [{ status: 'success', data: __.string }, __];
pattern = [{ status: 'success', data: __ }, __];

@@ -41,2 +42,84 @@ pattern = [{ status: 'error', error: new Error() }, __];

});
it('guard patterns should typecheck', () => {
const pattern1: Pattern<Input> = when(() => true);
const pattern2: Pattern<Input> = when((x) => {
const inferenceCheck: Input = x;
return true;
});
const pattern3: Pattern<Input> = [
when((state) => {
const inferenceCheck: State = state;
return !!state;
}),
when((event) => {
const inferenceCheck: Event = event;
return !!event;
}),
];
const pattern3_1: Pattern<Input> = [
__,
{ type: when((t: Event['type']) => true) },
];
const pattern4: Pattern<Input> = [
{
status: 'success',
data: when((d) => {
const inferenceCheck: string = d;
return true;
}),
},
__,
];
const pattern4_1: Pattern<Input> = [{ status: 'error', data: '' }, __];
const pattern5: Pattern<Input> = [
__,
{ type: when((t: Event['type']) => true) },
];
const isFetch = (type: string): type is 'fetch' => type === 'fetch';
const pattern6: Pattern<Input> = [__, { type: when(isFetch) }];
const pattern7: Pattern<{ x: string }> = {
x: when((x) => {
const inferenceCheck: string = x;
return true;
}),
};
const pattern8: Pattern<[{ x: string }]> = [
{
x: when((x) => {
const inferenceCheck: string = x;
return true;
}),
},
];
const pattern9: Pattern<[{ x: string }, { y: number }]> = [
{
x: when((x) => {
const inferenceCheck: string = x;
return true;
}),
},
{
y: when((y) => {
const inferenceCheck: number = y;
return true;
}),
},
];
const pattern10: Pattern<string | number> = when((x) => {
const inferenceCheck: string | number = x;
return true;
});
});
});

@@ -125,3 +208,3 @@

})
.with([{ id: Number, title: String }], (blogs) => {
.with([{ id: __.number, title: __.string }], (blogs) => {
const inferenceCheck: { id: number; title: string }[] = blogs;

@@ -149,6 +232,6 @@ return {

.with([], () => 0)
.with([Number, Number], ([x, y]) => x + y)
.with([Number, Number, Number], ([x, y, z]) => x + y + z)
.with([__.number, __.number], ([x, y]) => x + y)
.with([__.number, __.number, __.number], ([x, y, z]) => x + y + z)
.with(
[Number, Number, Number, Number],
[__.number, __.number, __.number, __.number],
([x, y, z, w]) => x + y + z + w

@@ -185,3 +268,3 @@ )

})
.with([String, Number], (x) => {
.with([__.string, __.number], (x) => {
const inferenceCheck: [string, number] = x;

@@ -256,3 +339,3 @@ return `not matching`;

const userPattern = { name: String };
const userPattern = { name: __.string };

@@ -314,2 +397,4 @@ const res = match<Map<string, { name: string }>, { name: string }>(

expect(containsGabAndYo(new Set([2]))).toEqual([false, false]);
expect(containsGabAndYo(new Set([__.number]))).toEqual([false, false]);
expect(containsGabAndYo(new Set([__.string]))).toEqual([false, false]);
});

@@ -327,7 +412,7 @@ });

const res = match<any, Blog | Error>(httpResult)
.with({ id: Number, title: String }, (r) => ({
.with({ id: __.number, title: __.string }, (r) => ({
id: r.id,
title: r.title,
}))
.with({ errorMessage: String }, (r) => new Error(r.errorMessage))
.with({ errorMessage: __.string }, (r) => new Error(r.errorMessage))
.otherwise(() => new Error('Client parse error'))

@@ -425,3 +510,6 @@ .run();

(x) => x.data.length > 3,
() => true
(x) => {
const inferenceCheck: { status: 'success'; data: string } = x;
return true;
}
)

@@ -434,2 +522,92 @@ .otherwise(() => false)

});
describe('pattern containing a when close', () => {
it('type of value in predicate should be infered', () => {
type Vec3 = { x: number; y: number; z: number };
const vec: Vec3 = { x: 20, y: 4, z: 2 };
const get = (vec: Vec3) =>
match<Vec3, boolean>(vec)
.with(
{
x: when((x): x is 20 => {
const inferenceCheck: number = x;
return x === 20;
}),
y: __.number,
},
(vec) => {
const inferenceCheck: Vec3 = vec;
return vec.y > 2;
}
)
.with(
when(() => true),
(x) => {
const inferenceCheck: Vec3 = vec;
return false;
}
)
.run();
expect(get(vec)).toEqual(true);
expect(get({ x: 2, y: 1, z: 0 })).toEqual(false);
});
});
describe('pattern containing a not close', () => {
it('should work at the top level', () => {
const get = (x: unknown) =>
match<unknown, string>(x)
.with(not(__.number), (x) => {
const inferenceCheck: unknown = x;
return 'not a number';
})
.with(not(__.string), (x) => {
const inferenceCheck: unknown = x;
return 'not a string';
})
.run();
expect(get(20)).toEqual('not a string');
expect(get('hello')).toEqual('not a number');
});
it('should work in a nested structure', () => {
type DS = { x: string | number; y: string | number };
const get = (x: DS) =>
match<DS, string>(x)
.with({ y: __.number, x: not(__.string) }, (x) => {
const inferenceCheck: { x: number; y: number } = x;
return 'yes';
})
.with(__, () => 'no')
.run();
expect(get({ x: 2, y: 2 })).toEqual('yes');
expect(get({ y: 2, x: 'hello' })).toEqual('no');
});
it('should discriminate union types correctly', () => {
const one = 'one';
const two = 'two';
const get = (x: 'one' | 'two') =>
match<'one' | 'two', string>(x)
.with(not(one), (x) => {
const inferenceCheck: 'two' = x;
return 'not 1';
})
.with(not(two), (x) => {
const inferenceCheck: 'one' = x;
return 'not 2';
})
.run();
expect(get('two')).toEqual('not 1');
expect(get('one')).toEqual('not 2');
});
it('type of value in predicate should be infered', () => {});
});
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc