Skip to content

fpc-js/utils

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

33 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@fpc/utils

Collection of generic utilities.

API

Clamps a number within a given range.

import { bound } from '@fpc/utils';

bound(1, 4, 6); // 4
bound(5, 4, 6); // 5
bound(7, 4, 6); // 6

Calls an object's method.

call(obj, 'methodName') throws a TypeError if obj.methodName isn't a function.

import { call } from '@fpc/utils';

const obj = {
  someMethod: arg => console.log('hello, ' + arg)
};

call(obj, 'someMethod', 'world'); // logs 'hello, world'

// same as '1,2,3'.split(',')
call('1,2,3', 'split', ','); // [ '1', '2', '3' ]

Creates a copy of a function that supports partial application.

import { curry } from '@fpc/utils';

const sum = curry((x, y) => x + y);
sum(1, 2); // 3

const add2 = sum(2);
add2(3); // 5

curry assumes the given function has exactly Function.length parameters. This behavior can be changed via the second argument:

import { curry } from '@fpc/utils';

const concatArrays = (...arrays) =>
  arrays.reduce((acc, array) => acc.concat(array), []);

concatArrays([ 1, 2 ], [ 3 ], [ 4, 5 ]); // [ 1, 2, 3, 4, 5 ]

curry(concatArrays); // TypeError: Expected positive integer, got 0
curry(concatArrays, 3)([ 1, 2 ], [ 3 ])([ 4 ]); // [ 1, 2, 3, 4 ]

Returns a deferred object, like the obsolete Promise.defer.

It should be used with caution when a promise is created in a function and have to be resolved or rejected in a different function.

Postpones the execution of a function. Takes an executor as argument and returns a promise just like the Promise constructor.

import { delay } from '@fpc/utils';

delay(resolve => resolve('hello')).then(console.log); // logs 'hello'

The executor always runs asynchronously (during the next event cycle):

new Promise((resolve, reject) => {
	console.log(1);
	resolve();
});

console.log(2);

// logs `1` then `2`
delay((resolve, reject) => {
  console.log(1);
  resolve();
});

console.log(2);

// logs `2` then `1`

Takes the delay in number of milliseconds as second argument (default to 0):

delay(resolve => resolve(1), 1000)
  .then(res => console.log(`After a whole second the result is ${res}`));

Throws an error but, unlike throw, it's an expression.

Wraps its input in an Error if it doesn't contain a stack and a message.

import { failWith } from '@fpc/utils';

const someFn = (...args) =>
  args.length > 0 || failWith(new Error('No args'));

Takes an iterable and returns the first element.

import { first } from '@fpc/utils';

first('abc'); // 'a'
first([ 1, 2, 3 ]); // 1

const iterable = {
  [Symbol.iterator]: () => ({
    next: () => ({
      done: false,
      value: 5,
    })
  })
};

first(iterable); // 5

Creates a copy of a function that takes its arguments in reversed order.

import { flip } from '@fpc/utils';

const cat = (...args) => args.reduce((acc, arg) => acc + arg, '');
const revCat = flip(cat);

revCat(1, 2, 3) === cat(3, 2, 1);

Works like Object.prototype.hasOwnProperty. This function exists to cover some edge-cases:

const obj = { prop: 'value', hasOwnProperty: '' };
obj.hasOwnProperty('value'); // TypeError: obj.hasOwnProperty is not a function
Object.create(null).hasOwnProperty('any'); // throws TypeError

See also no-prototype-builtins.

import { hasOwnProperty } from '@fpc/utils';

hasOwnProperty(null, 'lang'); // false
hasOwnProperty({}, 'lang'); // false
hasOwnProperty({ lang: 'it' }, 'lang'); // true

hasOwnProperty({}, 'toString'); // false

Shortcut for x => x.

Takes an iterable and returns the last element.

import { last } from '@fpc/utils';

last('abc'); // 'c'
last([ 1, 2, 3 ]); // 3

Returns a memoized version of a function.

import { lazy } from '@fpc/utils';

const counter = (() => {
  let count = 0;

  return () => count++;
})();

const lazyCounter = lazy(counter);

lazyCounter(); // 0
lazyCounter(); // 0
lazyCounter.update(); // 1

Logs its arguments to console, then returns the first one.

If global object console doesn't exist, acts like identity function without rising errors.

import { negate } from '@fpc/utils';

const isOdd = x => x % 2 !== 0;
[1, 2, 3, 4].filter(negate(isOdd)); // [ 2, 4 ]

Returns an object property value, or [undefined][Glob-undefined]. Doesn't throw errors.

import { prop } from '@fpc/utils';

prop({ propertyName: 'val' }, 'propertyName'); // 'val'
prop(null, 'propertyName'); // undefined
import { range } from '@fpc/utils';

range(1, 3); // [ 1, 2, 3 ]
range(-1, 1); // [ -1, 0, 1 ]
range(2, 10, 2); // [ 2, 4, 6, 8, 10 ]

Takes an iterable and returns the second element.

import { second } from '@fpc/utils';

second('abc'); // 'b'
second([ 1, 2, 3 ]); // 2

const iterable = {
  [Symbol.iterator]: () => ({
    next: () => ({
      done: false,
      value: 5,
    })
  })
};

second(iterable); // 5