init
This commit is contained in:
commit
6694c7eb9a
10 changed files with 328 additions and 0 deletions
113
src/lib/Chain.ts
Normal file
113
src/lib/Chain.ts
Normal file
|
@ -0,0 +1,113 @@
|
|||
import { Arr, Function, KeyOfType, Tail } from "./types.ts";
|
||||
import { map } from "./iter.ts";
|
||||
|
||||
export class Chain<T extends Arr> {
|
||||
run;
|
||||
|
||||
constructor(run: () => T) {
|
||||
this.run = run;
|
||||
}
|
||||
|
||||
static from<T>(value: T) {
|
||||
return new Chain(() => [value] as [T]);
|
||||
}
|
||||
|
||||
to<A extends Arr, O>(map: Function<[...T, ...A], O>, ...args: A) {
|
||||
const this_run = this.run;
|
||||
return new Chain(() => [map(...this_run(), ...args)] as [O]);
|
||||
}
|
||||
|
||||
front<I extends Arr>(...values: I) {
|
||||
const this_run = this.run;
|
||||
return new Chain(() => [...values, ...this_run()] as [...I, ...T]);
|
||||
}
|
||||
|
||||
back<I extends Arr>(...values: I) {
|
||||
const this_run = this.run;
|
||||
return new Chain(() => [...this_run(), ...values] as [...T, ...I]);
|
||||
}
|
||||
|
||||
nth<Index extends number>(index: Index) {
|
||||
const this_run = this.run;
|
||||
return new Chain(() => [this_run()[index]] as T[Index]);
|
||||
}
|
||||
|
||||
call<
|
||||
A extends Arr,
|
||||
Arg extends [...Tail<T>, ...A],
|
||||
M extends KeyOfType<T[0], Function<Arg>>,
|
||||
O extends ReturnType<T[0][M]>,
|
||||
>(method: M, ...args: A) {
|
||||
const this_run = this.run;
|
||||
return new Chain(() => {
|
||||
const [instance, ...rest] = this_run();
|
||||
return [instance[method](...rest, ...args)] as [O];
|
||||
});
|
||||
}
|
||||
|
||||
call_ignore<
|
||||
A extends Arr,
|
||||
Arg extends [...Tail<T>, ...A],
|
||||
M extends KeyOfType<T[0], Function<Arg>>,
|
||||
>(method: M, ...args: A) {
|
||||
const this_run = this.run;
|
||||
return new Chain(() => {
|
||||
const res1: T = this_run();
|
||||
const [instance, ...rest] = res1;
|
||||
instance[method](...rest, ...args);
|
||||
return res1;
|
||||
});
|
||||
}
|
||||
|
||||
call_keep<
|
||||
A extends Arr,
|
||||
Arg extends [...Tail<T>, ...A],
|
||||
M extends KeyOfType<T[0], Function<Arg>>,
|
||||
O extends ReturnType<T[0][M]>,
|
||||
>(method: M, ...args: A) {
|
||||
const this_run = this.run;
|
||||
return new Chain(() => {
|
||||
const res1 = this_run();
|
||||
const [instance, ...rest] = res1;
|
||||
const res2: O = instance[method](...rest, ...args);
|
||||
return [...res1, res2] as [...T, O];
|
||||
});
|
||||
}
|
||||
|
||||
construct<
|
||||
A extends Arr,
|
||||
C extends new (...args: [...T, ...A]) => unknown,
|
||||
O extends InstanceType<C>,
|
||||
>(class_: C, ...args: A) {
|
||||
const this_run = this.run;
|
||||
return new Chain(() => [new class_(...this_run(), ...args)] as [O]);
|
||||
}
|
||||
}
|
||||
Deno.test("example", async () => {
|
||||
const { assertEquals } = await import("https://deno.land/std@0.224.0/assert/mod.ts");
|
||||
|
||||
function times_2(num: number) {
|
||||
return num * 2;
|
||||
}
|
||||
|
||||
// type: number
|
||||
const [_o1] = Chain.from(3).to(times_2).run();
|
||||
// type: number
|
||||
const [_o2] = Chain.from(3).front(2, 5).to(Math.max).run();
|
||||
|
||||
function parse_and_add(text: string, num: number) {
|
||||
return parseInt(text) + num;
|
||||
}
|
||||
|
||||
// type: string
|
||||
const [_o3] = Chain.from(3).front("5").to(parse_and_add).call("toString").run();
|
||||
|
||||
// type: Set<number>
|
||||
const [_o4] = Chain.from([1, 2, 3])
|
||||
.call_keep("push", 7)
|
||||
.construct(Set<number>)
|
||||
.call_ignore("add", 8)
|
||||
.to(map, (item: number) => item.toString())
|
||||
.run();
|
||||
assertEquals([..._o4], ["1", "2", "3", "7", "8"]);
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue