Generate recursive typed functions
import { deepEqual } from 'assert' | |
type RecursiveFn<T> = (xs: T[], out?: T[]) => T[] | |
type OperatorFn<T> = (T: T, xs: T[], out: T[]) => T | void | |
type FactoryFn = <T>(fn: OperatorFn<T>) => RecursiveFn<T> | |
const recursiveFactory: FactoryFn = <T>(fn: OperatorFn<T>) => { | |
const recursive: RecursiveFn<T> = (xs, out = []) => { | |
const x = xs.shift() | |
const res = fn(x, xs, out) | |
if (res) { | |
out.push(res) | |
} | |
if (xs.length) { | |
return recursive(xs, out) | |
} | |
return out | |
} | |
return recursive | |
} | |
interface Status { | |
id: string; | |
effectiveDate: string; | |
type: string; | |
} | |
const reduceStatuses: OperatorFn<Status> = (x, _xs, out) => { | |
if (out.some(n => n.effectiveDate === x.effectiveDate && n.type === x.type)) { | |
return | |
} | |
return x | |
} | |
const reducer = recursiveFactory<Status>(reduceStatuses) | |
const input = [ | |
{ | |
id: '2e7c0c2b-9238-46cc-80ed-1e6cda05a1ca', | |
effectiveDate: '2019-10-01', | |
type: 'ACTIVE' | |
}, | |
{ | |
id: '60a93504-23bc-4f17-a4e3-d8e069c4600c', | |
effectiveDate: '2019-11-01', | |
type: 'TERMINATED' | |
}, | |
{ | |
id: 'b544ddde-3593-46a9-8280-8d4139bc261e', | |
effectiveDate: '2019-10-01', | |
type: 'ACTIVE' | |
} | |
] | |
const expected = [ | |
{ | |
id: '2e7c0c2b-9238-46cc-80ed-1e6cda05a1ca', | |
effectiveDate: '2019-10-01', | |
type: 'ACTIVE' | |
}, | |
{ | |
id: '60a93504-23bc-4f17-a4e3-d8e069c4600c', | |
effectiveDate: '2019-11-01', | |
type: 'TERMINATED' | |
}, | |
] | |
const output = reducer(input) | |
deepEqual(output, expected) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment