Security News
GitHub Removes Malicious Pull Requests Targeting Open Source Repositories
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
@typed/functions
Advanced tools
Well-typed collection of functions for working with functions
yarn add @typed/functions
# or
npm install --save @typed/functions
All functions are curried!
export type Arity0<A> = () => A
export type Arity1<A, B> = (value: A) => B
export type Arity10<A, B, C, D, E, F, G, H, I, J, K> = (
a: A,
b: B,
c: C,
d: D,
e: E,
f: F,
g: G,
h: H,
i: I,
j: J
) => K
export type Arity10N<A, B, C, D, E, F, G, H, I, J, R> = (
a: A,
b: B,
c: C,
d: D,
e: E,
f: F,
g: G,
h: H,
i: I,
j: J,
...args: Array<any>
) => R
export type Arity1Bound<that, A, B> = (this: that, a: A) => B
export type Arity1N<A, R> = (a: A, ...args: Array<any>) => R
export type Arity2<A, B, C> = (a: A, b: B) => C
export type Arity2Bound<that, A, B, C> = (this: that, a: A, b: B) => C
export type Arity2N<A, B, R> = (a: A, b: B, ...args: Array<any>) => R
export type Arity3<A, B, C, D> = (a: A, b: B, c: C) => D
export type Arity3Bound<that, A, B, C, D> = (this: that, a: A, b: B, c: C) => D
export type Arity3N<A, B, C, R> = (a: A, b: B, c: C, ...args: Array<any>) => R
export type Arity4<A, B, C, D, E> = (a: A, b: B, c: C, d: D) => E
export type Arity4Bound<that, A, B, C, D, E> = (this: that, a: A, b: B, c: C, d: D) => E
export type Arity4N<A, B, C, D, R> = (a: A, b: B, c: C, d: D, ...args: Array<any>) => R
export type Arity5<A, B, C, D, E, F> = (a: A, b: B, c: C, d: D, e: E) => F
export type Arity5Bound<that, A, B, C, D, E, F> = (this: that, a: A, b: B, c: C, d: D, e: E) => F
export type Arity5N<A, B, C, D, E, R> = (a: A, b: B, c: C, d: D, e: E, ...args: Array<any>) => R
export type Arity6<A, B, C, D, E, F, G> = (a: A, b: B, c: C, d: D, e: E, f: F) => G
export type Arity6N<A, B, C, D, E, F, R> = (
a: A,
b: B,
c: C,
d: D,
e: E,
f: F,
...args: Array<any>
) => R
export type Arity7<A, B, C, D, E, F, G, H> = (a: A, b: B, c: C, d: D, e: E, f: F, g: G) => H
export type Arity7N<A, B, C, D, E, F, G, R> = (
a: A,
b: B,
c: C,
d: D,
e: E,
f: F,
g: G,
...args: Array<any>
) => R
export type Arity8<A, B, C, D, E, F, G, H, I> = (
a: A,
b: B,
c: C,
d: D,
e: E,
f: F,
g: G,
h: H
) => I
export type Arity8N<A, B, C, D, E, F, G, H, R> = (
a: A,
b: B,
c: C,
d: D,
e: E,
f: F,
g: G,
h: H,
...args: Array<any>
) => R
export type Arity9<A, B, C, D, E, F, G, H, I, J> = (
a: A,
b: B,
c: C,
d: D,
e: E,
f: F,
g: G,
h: H,
i: I
) => J
export type Arity9N<A, B, C, D, E, F, G, H, I, R> = (
a: A,
b: B,
c: C,
d: D,
e: E,
f: F,
g: G,
h: H,
i: I,
...args: Array<any>
) => R
export type ArityN<R> = (...args: Array<any>) => R
export type Comparator<A> = (a: A, b: A) => ComparisonNumbers
export type ComparisonNumbers = -1 | 0 | 1
export type Curry10<A, B, C, D, E, F, G, H, I, J, K> = {
(a: A): Curry9<B, C, D, E, F, G, H, I, J, K>
(a: A, b: B): Curry8<C, D, E, F, G, H, I, J, K>
(a: A, b: B, c: C): Curry7<D, E, F, G, H, I, J, K>
(a: A, b: B, c: C, d: D): Curry6<E, F, G, H, I, J, K>
(a: A, b: B, c: C, d: D, e: E): Curry5<F, G, H, I, J, K>
(a: A, b: B, c: C, d: D, e: E, f: F): Curry4<G, H, I, J, K>
(a: A, b: B, c: C, d: D, e: E, f: F, g: G): Curry3<H, I, J, K>
(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H): Curry2<I, J, K>
(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I): Arity1<J, K>
(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J): K
}
export type Curry2<A, B, C> = {
(a: A): Arity1<B, C>
(a: A, b: B): C
}
export type Curry3<A, B, C, D> = {
(a: A): Curry2<B, C, D>
(a: A, b: B): Arity1<C, D>
(a: A, b: B, c: C): D
}
export type Curry4<A, B, C, D, E> = {
(a: A): Curry3<B, C, D, E>
(a: A, b: B): Curry2<C, D, E>
(a: A, b: B, c: C): Arity1<D, E>
(a: A, b: B, c: C, d: D): E
}
export type Curry5<A, B, C, D, E, F> = {
(a: A): Curry4<B, C, D, E, F>
(a: A, b: B): Curry3<C, D, E, F>
(a: A, b: B, c: C): Curry2<D, E, F>
(a: A, b: B, c: C, d: D): Arity1<E, F>
(a: A, b: B, c: C, d: D, e: E): F
}
export type Curry6<A, B, C, D, E, F, G> = {
(a: A): Curry5<B, C, D, E, F, G>
(a: A, b: B): Curry4<C, D, E, F, G>
(a: A, b: B, c: C): Curry3<D, E, F, G>
(a: A, b: B, c: C, d: D): Curry2<E, F, G>
(a: A, b: B, c: C, d: D, e: E): Arity1<F, G>
(a: A, b: B, c: C, d: D, e: E, f: F): G
}
export type Curry7<A, B, C, D, E, F, G, H> = {
(a: A): Curry6<B, C, D, E, F, G, H>
(a: A, b: B): Curry5<C, D, E, F, G, H>
(a: A, b: B, c: C): Curry4<D, E, F, G, H>
(a: A, b: B, c: C, d: D): Curry3<E, F, G, H>
(a: A, b: B, c: C, d: D, e: E): Curry2<F, G, H>
(a: A, b: B, c: C, d: D, e: E, f: F): Arity1<G, H>
(a: A, b: B, c: C, d: D, e: E, f: F, g: G): H
}
export type Curry8<A, B, C, D, E, F, G, H, I> = {
(a: A): Curry7<B, C, D, E, F, G, H, I>
(a: A, b: B): Curry6<C, D, E, F, G, H, I>
(a: A, b: B, c: C): Curry5<D, E, F, G, H, I>
(a: A, b: B, c: C, d: D): Curry4<E, F, G, H, I>
(a: A, b: B, c: C, d: D, e: E): Curry3<F, G, H, I>
(a: A, b: B, c: C, d: D, e: E, f: F): Curry2<G, H, I>
(a: A, b: B, c: C, d: D, e: E, f: F, g: G): Arity1<H, I>
(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H): I
}
export type Curry9<A, B, C, D, E, F, G, H, I, J> = {
(a: A): Curry8<B, C, D, E, F, G, H, I, J>
(a: A, b: B): Curry7<C, D, E, F, G, H, I, J>
(a: A, b: B, c: C): Curry6<D, E, F, G, H, I, J>
(a: A, b: B, c: C, d: D): Curry5<E, F, G, H, I, J>
(a: A, b: B, c: C, d: D, e: E): Curry4<F, G, H, I, J>
(a: A, b: B, c: C, d: D, e: E, f: F): Curry3<G, H, I, J>
(a: A, b: B, c: C, d: D, e: E, f: F, g: G): Curry2<H, I, J>
(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H): Arity1<I, J>
(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I): J
}
export type Predicate<A> = (value: A) => boolean
export type Predicate2<A> = (a: A, b: A) => boolean
A placeholder for partial
.
export const __: PlaceHolder = { '@@placeholder': true }
const isPlaceholder = (x: any): x is PlaceHolder => x['@@placeholder'] === true
Given a value returns a function that will always return that value.
export function always<A>(a: A) {
function constant(...args: Array<any>): A
function constant(): A {
return a
}
return constant
}
Given a list of arguments and a function, applies the function with the given arguments.
export const apply: Apply = function<A>(list: ArrayLike<any>, f?: (...args: Array<any>) => A) {
if (!f) return (f: (...args: Array<any>) => A) => __apply(list, f)
return __apply(list, f)
}
function __apply<A>(list: ArrayLike<any>, f: (...args: Array<any>) => A) {
switch (list.length) {
case 0:
return f()
case 1:
return f(list[0])
case 2:
return f(list[0], list[1])
case 3:
return f(list[0], list[1], list[2])
case 4:
return f(list[0], list[1], list[2], list[3])
case 5:
return f(list[0], list[1], list[2], list[3], list[4])
default:
return f.apply(null, list)
}
}
Right-to-left function composition.
export const compose: Compose = (...fns: Array<(value: any) => any>) => apply(fns.reverse(), pipe)
Given a function it returns a curried version of that function.
export const curry: CurryFn = function curry(fn: any) {
switch (fn.length) {
case 0:
return fn
case 1:
return fn
case 2:
return curry2(fn as Curry2<any, any, any>)
case 3:
return curry3(fn as Curry3<any, any, any, any>)
case 4:
return curry4(fn as Curry4<any, any, any, any, any>)
case 5:
return curry5(fn as Curry5<any, any, any, any, any, any>)
default:
return curryN(fn.length, fn)
}
}
export type CurryFn = {
<A>(f: () => A): () => A
<A, B>(f: Arity1<A, B>): Arity1<A, B>
<A, B, C>(f: Arity2<A, B, C>): Curry2<A, B, C>
<A, B, C, D>(f: Arity3<A, B, C, D>): Curry3<A, B, C, D>
<A, B, C, D, E>(f: Arity4<A, B, C, D, E>): Curry4<A, B, C, D, E>
<A, B, C, D, E, F>(f: Arity5<A, B, C, D, E, F>): Curry5<A, B, C, D, E, F>
<A, B, C, D, E, F, G>(f: Arity6<A, B, C, D, E, F, G>): Curry6<A, B, C, D, E, F, G>
<A, B, C, D, E, F, G, H>(f: Arity7<A, B, C, D, E, F, G, H>): Curry7<A, B, C, D, E, F, G, H>
<A, B, C, D, E, F, G, H, I>(f: Arity8<A, B, C, D, E, F, G, H, I>): Curry8<
A,
B,
C,
D,
E,
F,
G,
H,
I
>
<A, B, C, D, E, F, G, H, I, J>(f: Arity9<A, B, C, D, E, F, G, H, I, J>): Curry9<
A,
B,
C,
D,
E,
F,
G,
H,
I,
J
>
<A, B, C, D, E, F, G, H, I, J, K>(f: Arity10<A, B, C, D, E, F, G, H, I, J, K>): Curry10<
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K
>
}
Curries a function to n
arity.
export const curryN: CurryNFn = curriedN(
2,
(arity: number, f: ArityN<any>) => curriedN(arity, f, []),
[]
)
function curriedN(arity: number, f: ArityN<any>, previousArgs: Array<any>): ArityN<any> {
if (arity <= 1) return f
return function(...args: Array<any>) {
const concatArgs = previousArgs.concat(args)
if (concatArgs.length >= arity) return f.apply(this, concatArgs)
return curriedN(arity, f, concatArgs)
}
}
Flips the first 2 arguments of a function.
export const flip: Flip = function flip<A, B, C>(f: (a: A, b: B, ...args: Array<any>) => C) {
return curry(function(b: B, a: A, ...args: Array<any>): C {
return apply([a, b, ...args], f)
})
}
Returns the value passed in
export const id: Id = <A>(value: A): A => value
export type Id = {
<A>(value: A, ...args: Array<any>): A
}
Memoizes a function.
export const memoize = function<F extends Function>(f: F): F {
const cache = new Map<any, any>()
return (function(...args: Array<any>): any {
const key = args.reduce((x, y) => x + JSON.stringify(y), '')
if (cache.has(key)) return cache.get(key)
let result = f.apply(this, args)
if (typeof result === 'function') result = memoize(result)
cache.set(key, result)
return result
} as any) as F
}
Allows partially applying a function
export const partial: PartialFn = curry2(
(f: (...args: Array<any>) => any, args: Array<any>): any => {
const fnLength = f.length
const argsLength = args.length
if (fnLength === 0) return f
if (argsLength === 0) return curryN(fnLength as 2, f)
const placeholderAmount = args.filter(isPlaceholder).length
const expectedLength = Math.max(0, fnLength - argsLength) + placeholderAmount
function partiallyApplied(...otherArgs: Array<any>) {
if (placeholderAmount === 0) return apply(args.concat(otherArgs), f)
const combinedArgs: Array<any> = Array(fnLength)
for (let i = 0; i < combinedArgs.length; ++i)
combinedArgs[i] = isPlaceholder(args[i]) ? otherArgs.shift() : args[i]
return apply(combinedArgs.concat(otherArgs), f)
}
return curryN(expectedLength as 2, partiallyApplied)
}
)
Left-to-right function composition.
export const pipe: PipeFn = function pipe<A, B>(...fns: Array<Function>) {
return function(a: A): B {
switch (fns.length) {
case 1:
return fns[0](a)
case 2:
return fns[1](fns[0](a))
case 3:
return fns[2](fns[1](fns[0](a)))
case 4:
return fns[3](fns[2](fns[1](fns[0](a))))
case 5:
return fns[4](fns[3](fns[2](fns[1](fns[0](a)))))
default:
return fns.reduce((accumulator: any, value: Function) => value(accumulator), a)
}
}
}
FAQs
Well-typed collection of functions for working with functions
We found that @typed/functions demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
Security News
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
Security News
Node.js will be enforcing stricter semver-major PR policies a month before major releases to enhance stability and ensure reliable release candidates.