Skip to content
This repository has been archived by the owner on Jan 21, 2021. It is now read-only.

add generic type default arguments #1

Merged
merged 6 commits into from May 5, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 4 additions & 4 deletions lib/case.ts
@@ -1,13 +1,13 @@
import Handler from "./handler";
import Matcher from "./matcher";

export class Case<T> {
export class Case<T = any, C = any, M = any> {
constructor(
readonly condition: any,
readonly handler: Handler<T>,
readonly condition: C,
readonly handler: Handler<T, M>,
) {}

match(subject: any, matcher: Matcher): any {
match(subject: any, matcher: Matcher<M, C>): M {
return matcher(subject, this.condition);
}

Expand Down
12 changes: 6 additions & 6 deletions lib/context.ts
Expand Up @@ -3,22 +3,22 @@ import Handler from "./handler";
import Matcher from "./matcher";
import Switch from "./switch";

export class Context<T> {
export class Context<T = any, C = any, M = any> {
constructor(
protected sw: Switch<T>,
protected sw: Switch<T, C, M>,
) {}

matcher(matcher: Matcher): this {
matcher(matcher: Matcher<M, C>): this {
this.sw.setMatcher(matcher);
return this;
}

case(condition: any, handler: Handler<T>): this {
this.sw.addCase(new Case(condition, handler));
case(condition: C, handler: Handler<T, M>): this {
this.sw.addCase(new Case<T, C, M>(condition, handler));
return this;
}

default(handler: Handler<T>): this {
default(handler: Handler<T, M>): this {
this.sw.setDefaultHandler(handler);
return this;
}
Expand Down
4 changes: 2 additions & 2 deletions lib/handler.ts
@@ -1,5 +1,5 @@
export type Handler<T> = (match?: any) => T;
export type Handler<T = any, M = any> = (match?: M) => T;

export const VoidHandler: Handler<void> = () => undefined;
export const VoidHandler: Handler<void, void> = () => undefined;

export default Handler;
12 changes: 6 additions & 6 deletions lib/matcher.ts
@@ -1,24 +1,24 @@
export type Matcher = (subject: any, condition: any) => any;
export type Matcher<M = any, C = any> = (subject: any, condition: C) => M;

export const EqualityMatcher: Matcher = (subject: any, condition: any) => {
export const EqualityMatcher: Matcher<boolean> = (subject: any, condition: any) => {
return subject === condition;
};

export const RegexpMatcher: Matcher = (subject: string, condition: RegExp) => {
export const RegexpMatcher: Matcher<RegExpMatchArray | null, RegExp> = (subject: string, condition: RegExp) => {
return subject.match(condition);
};

export const IncludingMatcher: Matcher = (subject: any[], condition: any) => {
export const IncludingMatcher: Matcher<boolean> = (subject: any[], condition: any) => {
// return subject.includes(condition);
return subject.find(i => i === condition) !== undefined;
};

export const IncludedMatcher: Matcher = (subject: any, condition: any[]) => {
export const IncludedMatcher: Matcher<boolean, any[]> = (subject: any, condition: any[]) => {
// return condition.includes(subject);
return condition.find(i => i === subject) !== undefined;
};

export const FunctionMatcher: Matcher = (subject: any, fn: Function) => {
export const FunctionMatcher: Matcher<any, Function> = (subject: any, fn: Function) => {
return fn(subject);
};

Expand Down
18 changes: 9 additions & 9 deletions lib/switch.ts
Expand Up @@ -2,17 +2,17 @@ import Case from "./case";
import Handler, {VoidHandler} from "./handler";
import Matcher, {EqualityMatcher} from "./matcher";

export class Switch<T> {
protected cases: Case<T>[] = [];
export class Switch<T = any, C = any, M = any> {
protected cases: Case<T, C, M>[] = [];

constructor(
readonly subject: any,

protected matcher: Matcher = EqualityMatcher,
protected defaultHandler: Handler<T> = <Handler<T>>VoidHandler,
protected matcher: Matcher<M, C> = <Matcher<any, C>>EqualityMatcher,
protected defaultHandler: Handler<T, M> = <Handler<any>>VoidHandler,
) {}

addCase(...cases: Case<T>[]): this {
addCase(...cases: Case<T, C, M>[]): this {
cases.forEach(kase => {
this.cases.push(kase);
});
Expand All @@ -25,12 +25,12 @@ export class Switch<T> {
return this;
}

setMatcher(matcher: Matcher): this {
setMatcher(matcher: Matcher<M, C>): this {
this.matcher = matcher;
return this;
}

setDefaultHandler(handler: Handler<T>): this {
setDefaultHandler(handler: Handler<T, M>): this {
this.defaultHandler = handler;
return this;
}
Expand All @@ -43,8 +43,8 @@ export class Switch<T> {
return this.defaultHandler();
}

private findCase(): {matchedCase?: Case<T>, match?: any} {
let match: any = undefined;
private findCase(): {matchedCase?: Case<T, C, M>, match?: M} {
let match: M | undefined = undefined;

const matchedCase = this.cases.find(kase => {
match = kase.match(this.subject, this.matcher);
Expand Down
6 changes: 3 additions & 3 deletions lib/switz.ts
Expand Up @@ -6,9 +6,9 @@ import Switch from "./switch";
* @param subject An expression whose result is matched against each case condition.
* @param statement Function which determine cases, default handler, and matcher.
*/
export function switz<T>(subject: any, statement: (context: Context<T>) => void): T | void {
const sw = new Switch<T>(subject);
const context = new Context<T>(sw);
export function switz<T = any, C = any, M = any>(subject: any, statement: (context: Context<T, C, M>) => void): T | void {
const sw = new Switch<T, C, M>(subject);
const context = new Context<T, C, M>(sw);

statement(context);

Expand Down
9 changes: 9 additions & 0 deletions test/index.ts
Expand Up @@ -75,6 +75,15 @@ test("it can be used with type parameter", t => {
});

t.is(v, "bar");

const v2 = switz<string, RegExp, RegExpMatchArray | null>("yeaaaaaaaahhhhhhhhhhhhhhh", s => {
s.matcher(RegexpMatcher);
s.case(/h{10,}/, match => `yes, ${match![0].length} "h"s.`);
// s.case("fuz", () => 123); // ERROR!
s.default(() => "no");
});

t.is(v2, "yes, 15 \"h\"s.");
});

test("it can match subject and conditions with preset matcher", t => {
Expand Down