Import other modules into monorepo
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
This commit is contained in:
121
src/util/support/Pipe.ts
Normal file
121
src/util/support/Pipe.ts
Normal file
@@ -0,0 +1,121 @@
|
||||
/**
|
||||
* A closure that maps a given pipe item to a different type.
|
||||
*/
|
||||
export type PipeOperator<T, T2> = (subject: T) => T2
|
||||
|
||||
/**
|
||||
* A closure that maps a given pipe item to an item of the same type.
|
||||
*/
|
||||
export type ReflexivePipeOperator<T> = (subject: T) => T
|
||||
|
||||
/**
|
||||
* A class for writing chained/conditional operations in a data-flow manner.
|
||||
*
|
||||
* This is useful when you need to do a series of operations on an object, perhaps conditionally.
|
||||
*
|
||||
* @example
|
||||
* Say we have a Collection of items, and want to apply some transformations and filtering based on arguments:
|
||||
*
|
||||
* ```typescript
|
||||
* const collection = collect([1, 2, 3, 4, 5, 6, 7, 8, 9])
|
||||
*
|
||||
* function transform(collection, evensOnly = false, returnEntireCollection = false) {
|
||||
* return Pipe.wrap(collection)
|
||||
* .when(evensOnly, coll => {
|
||||
* return coll.filter(x => !(x % 2))
|
||||
* })
|
||||
* .unless(returnEntireCollection, coll => {
|
||||
* return coll.take(3)
|
||||
* })
|
||||
* .tap(coll => {
|
||||
* return coll.map(x => x * 2))
|
||||
* })
|
||||
* .get()
|
||||
* }
|
||||
*
|
||||
* transform(collection) // => Collection[2, 4, 6]
|
||||
*
|
||||
* transform(collection, true) // => Collection[4, 8, 12]
|
||||
*
|
||||
* transform(collection, false, true) // => Collection[2, 4, 6, 8, 10, 12, 14, 16, 18]
|
||||
* ```
|
||||
*/
|
||||
export class Pipe<T> {
|
||||
/**
|
||||
* Return a new Pipe containing the given subject.
|
||||
* @param subject
|
||||
*/
|
||||
static wrap<subject_t>(subject: subject_t) {
|
||||
return new Pipe<subject_t>(subject)
|
||||
}
|
||||
|
||||
constructor(
|
||||
/**
|
||||
* The item being operated on.
|
||||
*/
|
||||
private subject: T
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Apply the given operator to the item in the pipe, and return a new pipe with the result.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* Pipe.wrap(2)
|
||||
* .tap(x => x * 4)
|
||||
* .get() // => 8
|
||||
* ```
|
||||
*
|
||||
* @param op
|
||||
*/
|
||||
tap<T2>(op: PipeOperator<T, T2>) {
|
||||
return new Pipe(op(this.subject))
|
||||
}
|
||||
|
||||
/**
|
||||
* If `check` is truthy, apply the given operator to the item in the pipe and return the result.
|
||||
* Otherwise, just return the current pipe unchanged.
|
||||
*
|
||||
* @param check
|
||||
* @param op
|
||||
*/
|
||||
when(check: boolean, op: ReflexivePipeOperator<T>) {
|
||||
if ( check ) {
|
||||
return Pipe.wrap(op(this.subject))
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* If `check` is falsy, apply the given operator to the item in the pipe and return the result.
|
||||
* Otherwise, just return the current pipe unchanged.
|
||||
*
|
||||
* @param check
|
||||
* @param op
|
||||
*/
|
||||
unless(check: boolean, op: ReflexivePipeOperator<T>) {
|
||||
return this.when(!check, op)
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias of `unless()`.
|
||||
* @param check
|
||||
* @param op
|
||||
*/
|
||||
whenNot(check: boolean, op: ReflexivePipeOperator<T>) {
|
||||
return this.unless(check, op)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the item in the pipe.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* Pipe.wrap(4).get() // => 4
|
||||
* ```
|
||||
*/
|
||||
get(): T {
|
||||
return this.subject
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user