> | undefined): T\n```\n\nIt returns either `defaultValue` or the value of `property` in `obj`.\n\nTry this R.propOr example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\npropOr(defaultValue: T, property: P, obj: Partial> | undefined): T;\npropOr(defaultValue: T, property: P): (obj: Partial> | undefined) => T;\npropOr(defaultValue: T): {\n (property: P, obj: Partial> | undefined): T;\n (property: P): (obj: Partial> | undefined) => T;\n}\n```\n\n
\n\n\n\nR.propOr source
\n\n```javascript\nimport { curry } from './curry.js'\nimport { defaultTo } from './defaultTo.js'\n\nfunction propOrFn(\n defaultValue, property, obj\n){\n if (!obj) return defaultValue\n\n return defaultTo(defaultValue, obj[ property ])\n}\n\nexport const propOr = curry(propOrFn)\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { propOr } from './propOr.js'\n\ntest('propOr (result)', () => {\n const obj = { a : 1 }\n expect(propOr(\n 'default', 'a', obj\n )).toBe(1)\n expect(propOr(\n 'default', 'notExist', obj\n )).toBe('default')\n expect(propOr(\n 'default', 'notExist', null\n )).toBe('default')\n})\n\ntest('propOr (currying)', () => {\n const obj = { a : 1 }\n expect(propOr('default')('a', obj)).toBe(1)\n expect(propOr('default', 'a')(obj)).toBe(1)\n expect(propOr('default')('notExist', obj)).toBe('default')\n expect(propOr('default', 'notExist')(obj)).toBe('default')\n})\n```\n\n \n\n\n\nTypeScript test
\n\n```typescript\nimport {propOr} from 'rambda'\n\nconst obj = {foo: 'bar'}\nconst property = 'foo'\nconst fallback = 'fallback'\n\ndescribe('R.propOr', () => {\n it('happy', () => {\n const result = propOr(fallback, property, obj)\n result // $ExpectType string\n })\n it('curry 1', () => {\n const result = propOr(fallback)(property, obj)\n result // $ExpectType string\n })\n it('curry 2', () => {\n const result = propOr(fallback, property)(obj)\n result // $ExpectType string\n })\n it('curry 3', () => {\n const result = propOr(fallback)(property)(obj)\n result // $ExpectType string\n })\n})\n```\n\n \n\n[](#propOr)\n\n### props\n\n```typescript\n\nprops(propsToPick: P[], obj: Record
): T[]\n```\n\nIt takes list with properties `propsToPick` and returns a list with property values in `obj`.\n\nTry this R.props example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\nprops(propsToPick: P[], obj: Record
): T[];\nprops
(propsToPick: P[]): (obj: Record) => T[];\nprops
(propsToPick: P[]): (obj: Record
) => T[];\n```\n\n
\n\n\n\nR.props source
\n\n```javascript\nimport { isArray } from './_internals/isArray.js'\nimport { mapArray } from './map.js'\n\nexport function props(propsToPick, obj){\n if (arguments.length === 1){\n return _obj => props(propsToPick, _obj)\n }\n if (!isArray(propsToPick)){\n throw new Error('propsToPick is not a list')\n }\n\n return mapArray(prop => obj[ prop ], propsToPick)\n}\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { props } from './props.js'\n\nconst obj = {\n a : 1,\n b : 2,\n}\nconst propsToPick = [ 'a', 'c' ]\n\ntest('happy', () => {\n const result = props(propsToPick, obj)\n expect(result).toEqual([ 1, undefined ])\n})\n\ntest('curried', () => {\n const result = props(propsToPick)(obj)\n expect(result).toEqual([ 1, undefined ])\n})\n\ntest('wrong input', () => {\n expect(() => props(null)(obj)).toThrowErrorMatchingInlineSnapshot('\"propsToPick is not a list\"')\n})\n```\n\n \n\n\n\nTypeScript test
\n\n```typescript\nimport {props} from 'rambda'\n\nconst obj = {a: 1, b: 2}\n\ndescribe('R.props', () => {\n it('happy', () => {\n const result = props(['a', 'b'], obj)\n\n result // $ExpectType number[]\n })\n it('curried', () => {\n const result = props(['a', 'b'])(obj)\n\n result // $ExpectType number[]\n })\n})\n```\n\n \n\n[](#props)\n\n### propSatisfies\n\n```typescript\n\npropSatisfies(predicate: Predicate, property: string, obj: Record): boolean\n```\n\nIt returns `true` if the object property satisfies a given predicate.\n\nTry this R.propSatisfies example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\npropSatisfies(predicate: Predicate, property: string, obj: Record): boolean;\npropSatisfies(predicate: Predicate, property: string): (obj: Record) => boolean;\n```\n\n \n\n\n\nR.propSatisfies source
\n\n```javascript\nimport { curry } from './curry.js'\nimport { prop } from './prop.js'\n\nfunction propSatisfiesFn(\n predicate, property, obj\n){\n return predicate(prop(property, obj))\n}\n\nexport const propSatisfies = curry(propSatisfiesFn)\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { propSatisfies } from './propSatisfies.js'\n\nconst obj = { a : 1 }\n\ntest('when true', () => {\n expect(propSatisfies(\n x => x > 0, 'a', obj\n )).toBeTrue()\n})\n\ntest('when false', () => {\n expect(propSatisfies(x => x < 0, 'a')(obj)).toBeFalse()\n})\n```\n\n \n\n\n\nTypeScript test
\n\n```typescript\nimport {propSatisfies} from 'rambda'\n\nconst obj = {a: 1}\n\ndescribe('R.propSatisfies', () => {\n it('happy', () => {\n const result = propSatisfies(x => x > 0, 'a', obj)\n\n result // $ExpectType boolean\n })\n it('curried requires explicit type', () => {\n const result = propSatisfies(x => x > 0, 'a')(obj)\n\n result // $ExpectType boolean\n })\n})\n```\n\n \n\n[](#propSatisfies)\n\n### range\n\n```typescript\n\nrange(startInclusive: number, endExclusive: number): number[]\n```\n\nIt returns list of numbers between `startInclusive` to `endExclusive` markers.\n\nTry this R.range example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\nrange(startInclusive: number, endExclusive: number): number[];\nrange(startInclusive: number): (endExclusive: number) => number[];\n```\n\n \n\n\n\nR.range source
\n\n```javascript\nexport function range(start, end){\n if (arguments.length === 1) return _end => range(start, _end)\n\n if (Number.isNaN(Number(start)) || Number.isNaN(Number(end))){\n throw new TypeError('Both arguments to range must be numbers')\n }\n\n if (end < start) return []\n\n const len = end - start\n const willReturn = Array(len)\n\n for (let i = 0; i < len; i++){\n willReturn[ i ] = start + i\n }\n\n return willReturn\n}\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { range } from './range.js'\n\ntest('happy', () => {\n expect(range(0, 10)).toEqual([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ])\n})\n\ntest('end range is bigger than start range', () => {\n expect(range(7, 3)).toEqual([])\n expect(range(5, 5)).toEqual([])\n})\n\ntest('with bad input', () => {\n const throwMessage = 'Both arguments to range must be numbers'\n expect(() => range('a', 6)).toThrowWithMessage(Error, throwMessage)\n expect(() => range(6, 'z')).toThrowWithMessage(Error, throwMessage)\n})\n\ntest('curry', () => {\n expect(range(0)(10)).toEqual([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ])\n})\n```\n\n \n\n\n\nTypeScript test
\n\n```typescript\nimport {range} from 'rambda'\n\ndescribe('R.range', () => {\n it('happy', () => {\n const result = range(1, 4)\n\n result // $ExpectType number[]\n })\n it('curried', () => {\n const result = range(1)(4)\n\n result // $ExpectType number[]\n })\n})\n```\n\n \n\n[](#range)\n\n### reduce\n\nTry this R.reduce example in Rambda REPL\n\n[](#reduce)\n\n### reduceBy\n\nTry this R.reduceBy example in Rambda REPL\n\n[](#reduceBy)\n\n### reject\n\n```typescript\n\nreject(predicate: Predicate, list: T[]): T[]\n```\n\nIt has the opposite effect of `R.filter`.\n\nTry this R.reject example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\nreject(predicate: Predicate, list: T[]): T[];\nreject(predicate: Predicate): (list: T[]) => T[];\nreject(predicate: Predicate, obj: Dictionary): Dictionary;\nreject(predicate: Predicate): (obj: Dictionary) => Dictionary;\n```\n\n \n\n\n\nR.reject source
\n\n```javascript\nimport { filter } from './filter.js'\n\nexport function reject(predicate, list){\n if (arguments.length === 1) return _list => reject(predicate, _list)\n\n return filter(x => !predicate(x), list)\n}\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { reject } from './reject.js'\n\nconst isOdd = n => n % 2 === 1\n\ntest('with array', () => {\n expect(reject(isOdd)([ 1, 2, 3, 4 ])).toEqual([ 2, 4 ])\n})\n\ntest('with object', () => {\n const obj = {\n a : 1,\n b : 2,\n c : 3,\n d : 4,\n }\n expect(reject(isOdd, obj)).toEqual({\n b : 2,\n d : 4,\n })\n})\n```\n\n \n\n\n\nTypeScript test
\n\n```typescript\nimport {reject} from 'rambda'\n\ndescribe('R.reject with array', () => {\n it('happy', () => {\n const result = reject(\n x => {\n x // $ExpectType number\n return x > 1\n },\n [1, 2, 3]\n )\n result // $ExpectType number[]\n })\n it('curried require explicit type', () => {\n const result = reject(x => {\n x // $ExpectType number\n return x > 1\n })([1, 2, 3])\n result // $ExpectType number[]\n })\n})\n\ndescribe('R.reject with objects', () => {\n it('happy', () => {\n const result = reject(\n x => {\n x // $ExpectType number\n\n return x > 1\n },\n {a: 1, b: 2}\n )\n result // $ExpectType Dictionary\n })\n it('curried require dummy type', () => {\n const result = reject(x => {\n return x > 1\n })({a: 1, b: 2})\n result // $ExpectType Dictionary\n })\n})\n```\n\n \n\n[](#reject)\n\n### removeIndex\n\n```typescript\n\nremoveIndex(index: number, list: T[]): T[]\n```\n\nIt returns a copy of `list` input with removed `index`.\n\nTry this R.removeIndex example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\nremoveIndex(index: number, list: T[]): T[];\nremoveIndex(index: number): (list: T[]) => T[];\n```\n\n \n\n\n\nR.removeIndex source
\n\n```javascript\nexport function removeIndex(index, list){\n if (arguments.length === 1) return _list => removeIndex(index, _list)\n if (index <= 0) return list.slice(1)\n if (index >= list.length - 1) return list.slice(0, list.length - 1)\n\n return [ ...list.slice(0, index), ...list.slice(index + 1) ]\n}\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { removeIndex } from './removeIndex.js'\n\nconst list = [ 1, 2, 3, 4 ]\n\ntest('first or before first index', () => {\n expect(removeIndex(-2, list)).toEqual([ 2, 3, 4 ])\n expect(removeIndex(-2)(list)).toEqual([ 2, 3, 4 ])\n})\n\ntest('last or after last index', () => {\n expect(removeIndex(4, list)).toEqual([ 1, 2, 3 ])\n expect(removeIndex(10, list)).toEqual([ 1, 2, 3 ])\n})\n\ntest('middle index', () => {\n expect(removeIndex(1, list)).toEqual([ 1, 3, 4 ])\n expect(removeIndex(2, list)).toEqual([ 1, 2, 4 ])\n})\n```\n\n \n\n\n\nTypeScript test
\n\n```typescript\nimport {removeIndex} from 'rambda'\n\ndescribe('R.removeIndex', () => {\n it('happy', () => {\n const result = removeIndex(1, [1, 2, 3])\n\n result // $ExpectType number[]\n })\n it('curried', () => {\n const result = removeIndex(1)([1, 2, 3])\n\n result // $ExpectType number[]\n })\n})\n```\n\n \n\n[](#removeIndex)\n\n### repeat\n\n```typescript\n\nrepeat(x: T): (timesToRepeat: number) => T[]\n```\n\nTry this R.repeat example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\nrepeat(x: T): (timesToRepeat: number) => T[];\nrepeat(x: T, timesToRepeat: number): T[];\n```\n\n \n\n\n\nR.repeat source
\n\n```javascript\nexport function repeat(x, timesToRepeat){\n if (arguments.length === 1){\n return _timesToRepeat => repeat(x, _timesToRepeat)\n }\n\n return Array(timesToRepeat).fill(x)\n}\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { repeat } from './repeat.js'\n\ntest('repeat', () => {\n expect(repeat('')(3)).toEqual([ '', '', '' ])\n expect(repeat('foo', 3)).toEqual([ 'foo', 'foo', 'foo' ])\n\n const obj = {}\n const arr = repeat(obj, 3)\n\n expect(arr).toEqual([ {}, {}, {} ])\n\n expect(arr[ 0 ] === arr[ 1 ]).toBeTrue()\n})\n```\n\n \n\n\n\nTypeScript test
\n\n```typescript\nimport {repeat} from 'rambda'\n\ndescribe('R.repeat', () => {\n it('happy', () => {\n const result = repeat(4, 7)\n\n result // $ExpectType number[]\n })\n it('curried', () => {\n const result = repeat(4)(7)\n\n result // $ExpectType number[]\n })\n})\n```\n\n \n\n[](#repeat)\n\n### replace\n\n```typescript\n\nreplace(strOrRegex: RegExp | string, replacer: RegExpReplacer, str: string): string\n```\n\nIt replaces `strOrRegex` found in `str` with `replacer`.\n\nTry this R.replace example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\nreplace(strOrRegex: RegExp | string, replacer: RegExpReplacer, str: string): string;\nreplace(strOrRegex: RegExp | string, replacer: RegExpReplacer): (str: string) => string;\nreplace(strOrRegex: RegExp | string): (replacer: RegExpReplacer) => (str: string) => string;\n```\n\n \n\n\n\nR.replace source
\n\n```javascript\nimport { curry } from './curry.js'\n\nfunction replaceFn(\n pattern, replacer, str\n){\n return str.replace(pattern, replacer)\n}\n\nexport const replace = curry(replaceFn)\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { replace } from './replace.js'\n\ntest('happy', () => {\n expect(replace(\n /\\s/g, '|', 'foo bar baz'\n )).toBe('foo|bar|baz')\n})\n\ntest('with function as replacer input', () => {\n expect(replace(\n /\\s/g,\n (\n match, offset, str\n ) => {\n expect(match).toBe(' ')\n expect([ 3, 7 ].includes(offset)).toBeTrue()\n expect(str).toBe('foo bar baz')\n\n return '|'\n },\n 'foo bar baz'\n )).toBe('foo|bar|baz')\n})\n```\n\n \n\n\n\nTypeScript test
\n\n```typescript\nimport {replace} from 'rambda'\n\nconst str = 'foo bar foo'\nconst replacer = 'bar'\n\ndescribe('R.replace', () => {\n it('happy', () => {\n const result = replace(/foo/g, replacer, str)\n\n result // $ExpectType string\n })\n it('with string as search pattern', () => {\n const result = replace('foo', replacer, str)\n\n result // $ExpectType string\n })\n it('with function as replacer', () => {\n const result = replace('f(o)o', (m: string, p1: string, offset: number) => {\n m // $ExpectType string\n p1 // $ExpectType string\n offset // $ExpectType number\n return p1\n }, str)\n\n result // $ExpectType string\n })\n})\n\ndescribe('R.replace - curried', () => {\n it('happy', () => {\n const result = replace(/foo/g, replacer)(str)\n\n result // $ExpectType string\n })\n it('with string as search pattern', () => {\n const result = replace('foo', replacer)(str)\n\n result // $ExpectType string\n })\n it('with function as replacer', () => {\n const result = replace('f(o)o')((m: string, p1: string, offset: number) => {\n m // $ExpectType string\n p1 // $ExpectType string\n offset // $ExpectType number\n return p1\n })(str)\n\n result // $ExpectType string\n })\n})\n```\n\n \n\n[](#replace)\n\n### reverse\n\n```typescript\n\nreverse(input: T[]): T[]\n```\n\nIt returns a reversed copy of list or string `input`.\n\nTry this R.reverse example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\nreverse(input: T[]): T[];\nreverse(input: string): string;\n```\n\n \n\n\n\nR.reverse source
\n\n```javascript\nexport function reverse(listOrString) {\n if (typeof listOrString === 'string') {\n return listOrString.split('').reverse().join('')\n }\n\n const clone = listOrString.slice()\n\n return clone.reverse()\n}\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport {reverse} from './reverse.js'\n\ntest('happy', () => {\n expect(reverse([1, 2, 3])).toEqual([3, 2, 1])\n})\n\ntest('with string', () => {\n expect(reverse('baz')).toBe('zab')\n})\n\ntest(\"it doesn't mutate\", () => {\n const arr = [1, 2, 3]\n\n expect(reverse(arr)).toEqual([3, 2, 1])\n\n expect(arr).toEqual([1, 2, 3])\n})\n```\n\n \n\n\n\nTypeScript test
\n\n```typescript\nimport {reverse} from 'rambda'\n\nconst list = [1, 2, 3, 4, 5]\n\ndescribe('R.reverse', () => {\n it('happy', () => {\n const result = reverse(list)\n result // $ExpectType number[]\n })\n})\n```\n\n \n\n[](#reverse)\n\n### set\n\n```typescript\n\nset(lens: Lens): {\n (a: A): (obj: S) => S\n (a: A, obj: S): S\n}\n```\n\nIt returns a copied **Object** or **Array** with modified `lens` focus set to `replacer` value.\n\nTry this R.set example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\nset(lens: Lens): {\n (a: A): (obj: S) => S\n (a: A, obj: S): S\n};\nset(lens: Lens, a: A): (obj: S) => S;\nset(lens: Lens, a: A, obj: S): S;\n```\n\n \n\n\n\nR.set source
\n\n```javascript\nimport {always} from './always.js'\nimport {curry} from './curry.js'\nimport {over} from './over.js'\n\nfunction setFn(lens, replacer, x) {\n return over(lens, always(replacer), x)\n}\n\nexport const set = curry(setFn)\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport {assoc} from './assoc.js'\nimport {lens} from './lens.js'\nimport {lensIndex} from './lensIndex.js'\nimport {lensPath} from './lensPath.js'\nimport {prop} from './prop.js'\nimport {set} from './set.js'\n\nconst testObject = {\n foo: 'bar',\n baz: {\n a: 'x',\n b: 'y',\n },\n}\n\ntest('assoc lens', () => {\n const assocLens = lens(prop('foo'), assoc('foo'))\n const result = set(assocLens, 'FOO', testObject)\n const expected = {\n ...testObject,\n foo: 'FOO',\n }\n expect(result).toEqual(expected)\n})\n\ntest('path lens', () => {\n const pathLens = lensPath('baz.a')\n const result = set(pathLens, 'z', testObject)\n const expected = {\n ...testObject,\n baz: {\n a: 'z',\n b: 'y',\n },\n }\n expect(result).toEqual(expected)\n})\n\ntest('index lens', () => {\n const indexLens = lensIndex(0)\n\n const result = set(indexLens, 3, [1, 2])\n expect(result).toEqual([3, 2])\n})\n```\n\n \n\n[](#set)\n\n### slice\n\n```typescript\n\nslice(from: number, to: number, input: string): string\n```\n\nTry this R.slice example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\nslice(from: number, to: number, input: string): string;\nslice(from: number, to: number, input: T[]): T[];\nslice(from: number, to: number): {\n (input: string): string;\n (input: T[]): T[];\n};\nslice(from: number): {\n (to: number, input: string): string;\n (to: number, input: T[]): T[];\n};\n```\n\n \n\n\n\nR.slice source
\n\n```javascript\nimport { curry } from './curry.js'\n\nfunction sliceFn(\n from, to, list\n){\n return list.slice(from, to)\n}\n\nexport const slice = curry(sliceFn)\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { slice } from './slice.js'\n\ntest('slice', () => {\n expect(slice(\n 1, 3, [ 'a', 'b', 'c', 'd' ]\n )).toEqual([ 'b', 'c' ])\n expect(slice(\n 1, Infinity, [ 'a', 'b', 'c', 'd' ]\n )).toEqual([ 'b', 'c', 'd' ])\n expect(slice(\n 0, -1, [ 'a', 'b', 'c', 'd' ]\n )).toEqual([ 'a', 'b', 'c' ])\n expect(slice(\n -3, -1, [ 'a', 'b', 'c', 'd' ]\n )).toEqual([ 'b', 'c' ])\n expect(slice(\n 0, 3, 'ramda'\n )).toBe('ram')\n})\n```\n\n \n\n\n\nTypeScript test
\n\n```typescript\nimport {slice} from 'rambda'\n\nconst list = [1, 2, 3, 4, 5]\n\ndescribe('R.slice', () => {\n it('happy', () => {\n const result = slice(1, 3, list)\n result // $ExpectType number[]\n })\n it('curried', () => {\n const result = slice(1, 3)(list)\n result // $ExpectType number[]\n })\n})\n```\n\n \n\n[](#slice)\n\n### sort\n\n```typescript\n\nsort(sortFn: (a: T, b: T) => number, list: T[]): T[]\n```\n\nIt returns copy of `list` sorted by `sortFn` function, where `sortFn` needs to return only `-1`, `0` or `1`.\n\nTry this R.sort example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\nsort(sortFn: (a: T, b: T) => number, list: T[]): T[];\nsort(sortFn: (a: T, b: T) => number): (list: T[]) => T[];\n```\n\n \n\n\n\nR.sort source
\n\n```javascript\nimport { cloneList } from './_internals/cloneList.js'\n\nexport function sort(sortFn, list){\n if (arguments.length === 1) return _list => sort(sortFn, _list)\n\n return cloneList(list).sort(sortFn)\n}\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { sort } from './sort.js'\n\nconst fn = (a, b) => a > b ? 1 : -1\n\ntest('sort', () => {\n expect(sort((a, b) => a - b)([ 2, 3, 1 ])).toEqual([ 1, 2, 3 ])\n})\n\ntest('it doesn\\'t mutate', () => {\n const list = [ 'foo', 'bar', 'baz' ]\n\n expect(sort(fn, list)).toEqual([ 'bar', 'baz', 'foo' ])\n\n expect(list[ 0 ]).toBe('foo')\n expect(list[ 1 ]).toBe('bar')\n expect(list[ 2 ]).toBe('baz')\n})\n```\n\n \n\n\n\nTypeScript test
\n\n```typescript\nimport {sort} from 'rambda'\n\nconst list = [3, 0, 5, 2, 1]\n\nfunction sortFn(a: number, b: number): number {\n return a > b ? 1 : -1\n}\n\ndescribe('R.sort', () => {\n it('happy', () => {\n const result = sort(sortFn, list)\n result // $ExpectType number[]\n })\n it('curried', () => {\n const result = sort(sortFn)(list)\n result // $ExpectType number[]\n })\n})\n```\n\n \n\n[](#sort)\n\n### sortBy\n\n```typescript\n\nsortBy(sortFn: (a: T) => Ord, list: T[]): T[]\n```\n\nIt returns copy of `list` sorted by `sortFn` function, where `sortFn` function returns a value to compare, i.e. it doesn't need to return only `-1`, `0` or `1`.\n\nTry this R.sortBy example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\nsortBy(sortFn: (a: T) => Ord, list: T[]): T[];\nsortBy(sortFn: (a: T) => Ord): (list: T[]) => T[];\nsortBy(sortFn: (a: any) => Ord): (list: T[]) => T[];\n```\n\n \n\n\n\nR.sortBy source
\n\n```javascript\nimport { cloneList } from './_internals/cloneList.js'\n\nexport function sortBy(sortFn, list){\n if (arguments.length === 1) return _list => sortBy(sortFn, _list)\n\n const clone = cloneList(list)\n\n return clone.sort((a, b) => {\n const aSortResult = sortFn(a)\n const bSortResult = sortFn(b)\n\n if (aSortResult === bSortResult) return 0\n\n return aSortResult < bSortResult ? -1 : 1\n })\n}\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { compose } from './compose.js'\nimport { prop } from './prop.js'\nimport { sortBy } from './sortBy.js'\nimport { toLower } from './toLower.js'\n\ntest('happy', () => {\n const input = [ { a : 2 }, { a : 1 }, { a : 1 }, { a : 3 } ]\n const expected = [ { a : 1 }, { a : 1 }, { a : 2 }, { a : 3 } ]\n\n const result = sortBy(x => x.a)(input)\n expect(result).toEqual(expected)\n})\n\ntest('with compose', () => {\n const alice = {\n name : 'ALICE',\n age : 101,\n }\n const bob = {\n name : 'Bob',\n age : -10,\n }\n const clara = {\n name : 'clara',\n age : 314.159,\n }\n const people = [ clara, bob, alice ]\n const sortByNameCaseInsensitive = sortBy(compose(toLower, prop('name')))\n\n expect(sortByNameCaseInsensitive(people)).toEqual([ alice, bob, clara ])\n})\n```\n\n \n\n\n\nTypeScript test
\n\n```typescript\nimport {sortBy, pipe} from 'rambda'\n\ninterface Input {\n a: number,\n}\n\ndescribe('R.sortBy', () => {\n it('passing type to sort function', () => {\n function fn(x: any): number {\n return x.a\n }\n function fn2(x: Input): number {\n return x.a\n }\n\n const input = [{a: 2}, {a: 1}, {a: 0}]\n const result = sortBy(fn, input)\n const curriedResult = sortBy(fn2)(input)\n\n result // $ExpectType { a: number; }[]\n curriedResult // $ExpectType Input[]\n result[0].a // $ExpectType number\n curriedResult[0].a // $ExpectType number\n })\n it('passing type to sort function and list', () => {\n function fn(x: Input): number {\n return x.a\n }\n\n const input: Input[] = [{a: 2}, {a: 1}, {a: 0}]\n const result = sortBy(fn, input)\n const curriedResult = sortBy(fn)(input)\n\n result // $ExpectType Input[]\n curriedResult // $ExpectType Input[]\n result[0].a // $ExpectType number\n })\n it('with R.pipe', () => {\n interface Obj {\n value: number,\n }\n const fn = pipe(sortBy(x => x.value))\n\n const result = fn([{value: 1}, {value: 2}])\n result // $ExpectType Obj[]\n })\n})\n```\n\n \n\n[](#sortBy)\n\n### sortWith\n\nTry this R.sortWith example in Rambda REPL\n\n[](#sortWith)\n\n### split\n\n```typescript\n\nsplit(separator: string | RegExp): (str: string) => string[]\n```\n\nCurried version of `String.prototype.split`\n\nTry this R.split example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\nsplit(separator: string | RegExp): (str: string) => string[];\nsplit(separator: string | RegExp, str: string): string[];\n```\n\n \n\n\n\nR.split source
\n\n```javascript\nexport function split(separator, str){\n if (arguments.length === 1) return _str => split(separator, _str)\n\n return str.split(separator)\n}\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { split } from './split.js'\n\nconst str = 'foo|bar|baz'\nconst splitChar = '|'\nconst expected = [ 'foo', 'bar', 'baz' ]\n\ntest('happy', () => {\n expect(split(splitChar, str)).toEqual(expected)\n})\n\ntest('curried', () => {\n expect(split(splitChar)(str)).toEqual(expected)\n})\n```\n\n \n\n\n\nTypeScript test
\n\n```typescript\nimport {split} from 'rambda'\n\nconst str = 'foo|bar|baz'\nconst splitChar = '|'\n\ndescribe('R.split', () => {\n it('happy', () => {\n const result = split(splitChar, str)\n\n result // $ExpectType string[]\n })\n it('curried', () => {\n const result = split(splitChar)(str)\n\n result // $ExpectType string[]\n })\n})\n```\n\n \n\n[](#split)\n\n### splitAt\n\n```typescript\n\nsplitAt(index: number, input: T[]): [T[], T[]]\n```\n\nIt splits string or array at a given index.\n\nTry this R.splitAt example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\nsplitAt(index: number, input: T[]): [T[], T[]];\nsplitAt(index: number, input: string): [string, string];\nsplitAt(index: number): {\n (input: T[]): [T[], T[]];\n (input: string): [string, string];\n};\n```\n\n \n\n\n\nR.splitAt source
\n\n```javascript\nimport { isArray } from './_internals/isArray.js'\nimport { drop } from './drop.js'\nimport { maybe } from './maybe.js'\nimport { take } from './take.js'\n\nexport function splitAt(index, input){\n if (arguments.length === 1){\n return _list => splitAt(index, _list)\n }\n if (!input) throw new TypeError(`Cannot read property 'slice' of ${ input }`)\n\n if (!isArray(input) && typeof input !== 'string') return [ [], [] ]\n\n const correctIndex = maybe(\n index < 0,\n input.length + index < 0 ? 0 : input.length + index,\n index\n )\n\n return [ take(correctIndex, input), drop(correctIndex, input) ]\n}\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { splitAt as splitAtRamda } from 'ramda'\n\nimport { splitAt } from './splitAt.js'\n\nconst list = [ 1, 2, 3 ]\nconst str = 'foo bar'\n\ntest('with array', () => {\n const result = splitAt(2, list)\n expect(result).toEqual([ [ 1, 2 ], [ 3 ] ])\n})\n\ntest('with array - index is negative number', () => {\n const result = splitAt(-6, list)\n expect(result).toEqual([ [], list ])\n})\n\ntest('with array - index is out of scope', () => {\n const result = splitAt(4, list)\n expect(result).toEqual([ [ 1, 2, 3 ], [] ])\n})\n\ntest('with string', () => {\n const result = splitAt(4, str)\n expect(result).toEqual([ 'foo ', 'bar' ])\n})\n\ntest('with string - index is negative number', () => {\n const result = splitAt(-2, str)\n expect(result).toEqual([ 'foo b', 'ar' ])\n})\n\ntest('with string - index is out of scope', () => {\n const result = splitAt(10, str)\n expect(result).toEqual([ str, '' ])\n})\n\ntest('with array - index is out of scope', () => {\n const result = splitAt(4)(list)\n expect(result).toEqual([ [ 1, 2, 3 ], [] ])\n})\n\nconst badInputs = [ 1, true, /foo/g, {} ]\nconst throwingBadInputs = [ null, undefined ]\n\ntest('with bad inputs', () => {\n throwingBadInputs.forEach(badInput => {\n expect(() => splitAt(1, badInput)).toThrowWithMessage(TypeError,\n `Cannot read property 'slice' of ${ badInput }`)\n expect(() => splitAtRamda(1, badInput)).toThrowWithMessage(TypeError,\n `Cannot read properties of ${ badInput } (reading 'slice')`)\n })\n\n badInputs.forEach(badInput => {\n const result = splitAt(1, badInput)\n const ramdaResult = splitAtRamda(1, badInput)\n expect(result).toEqual(ramdaResult)\n })\n})\n```\n\n \n\n\n\nTypeScript test
\n\n```typescript\nimport {splitAt} from 'rambda'\n\nconst index = 1\nconst str = 'foo'\nconst list = [1, 2, 3]\n\ndescribe('R.splitAt with array', () => {\n it('happy', () => {\n const result = splitAt(index, list)\n\n result // $ExpectType [number[], number[]]\n })\n it('curried', () => {\n const result = splitAt(index)(list)\n\n result // $ExpectType [number[], number[]]\n })\n})\n\ndescribe('R.splitAt with string', () => {\n it('happy', () => {\n const result = splitAt(index, str)\n\n result // $ExpectType [string, string]\n })\n it('curried', () => {\n const result = splitAt(index)(str)\n\n result // $ExpectType [string, string]\n })\n})\n```\n\n \n\n[](#splitAt)\n\n### splitEvery\n\n```typescript\n\nsplitEvery(sliceLength: number, input: T[]): (T[])[]\n```\n\nIt splits `input` into slices of `sliceLength`.\n\nTry this R.splitEvery example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\nsplitEvery(sliceLength: number, input: T[]): (T[])[];\nsplitEvery(sliceLength: number, input: string): string[];\nsplitEvery(sliceLength: number): {\n (input: string): string[];\n (input: T[]): (T[])[];\n};\n```\n\n \n\n\n\nR.splitEvery source
\n\n```javascript\nexport function splitEvery(sliceLength, listOrString){\n if (arguments.length === 1){\n return _listOrString => splitEvery(sliceLength, _listOrString)\n }\n\n if (sliceLength < 1){\n throw new Error('First argument to splitEvery must be a positive integer')\n }\n\n const willReturn = []\n let counter = 0\n\n while (counter < listOrString.length){\n willReturn.push(listOrString.slice(counter, counter += sliceLength))\n }\n\n return willReturn\n}\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { splitEvery } from './splitEvery.js'\n\ntest('happy', () => {\n expect(splitEvery(3, [ 1, 2, 3, 4, 5, 6, 7 ])).toEqual([\n [ 1, 2, 3 ],\n [ 4, 5, 6 ],\n [ 7 ],\n ])\n\n expect(splitEvery(3)('foobarbaz')).toEqual([ 'foo', 'bar', 'baz' ])\n})\n\ntest('with bad input', () => {\n expect(() =>\n expect(splitEvery(0)('foo')).toEqual([ 'f', 'o', 'o' ])).toThrowErrorMatchingInlineSnapshot('\"First argument to splitEvery must be a positive integer\"')\n})\n```\n\n \n\n\n\nTypeScript test
\n\n```typescript\nimport {splitEvery} from 'rambda'\n\nconst list = [1, 2, 3, 4, 5, 6, 7]\n\ndescribe('R.splitEvery', () => {\n it('happy', () => {\n const result = splitEvery(3, list)\n\n result // $ExpectType number[][]\n })\n it('curried', () => {\n const result = splitEvery(3)(list)\n\n result // $ExpectType number[][]\n })\n})\n```\n\n \n\n[](#splitEvery)\n\n### splitWhen\n\n```typescript\n\nsplitWhen(predicate: Predicate, list: U[]): (U[])[]\n```\n\nIt splits `list` to two arrays according to a `predicate` function. \n\nThe first array contains all members of `list` before `predicate` returns `true`.\n\nTry this R.splitWhen example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\nsplitWhen(predicate: Predicate, list: U[]): (U[])[];\nsplitWhen(predicate: Predicate): (list: U[]) => (U[])[];\n```\n\n \n\n\n\nR.splitWhen source
\n\n```javascript\nexport function splitWhen(predicate, input){\n if (arguments.length === 1){\n return _input => splitWhen(predicate, _input)\n }\n if (!input)\n throw new TypeError(`Cannot read property 'length' of ${ input }`)\n\n const preFound = []\n const postFound = []\n let found = false\n let counter = -1\n\n while (counter++ < input.length - 1){\n if (found){\n postFound.push(input[ counter ])\n } else if (predicate(input[ counter ])){\n postFound.push(input[ counter ])\n found = true\n } else {\n preFound.push(input[ counter ])\n }\n }\n\n return [ preFound, postFound ]\n}\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { splitWhen as splitWhenRamda } from 'ramda'\n\nimport { equals } from './equals.js'\nimport { splitWhen } from './splitWhen.js'\n\nconst list = [ 1, 2, 1, 2 ]\n\ntest('happy', () => {\n const result = splitWhen(equals(2), list)\n expect(result).toEqual([ [ 1 ], [ 2, 1, 2 ] ])\n})\n\ntest('when predicate returns false', () => {\n const result = splitWhen(equals(3))(list)\n expect(result).toEqual([ list, [] ])\n})\n\nconst badInputs = [ 1, true, /foo/g, {} ]\nconst throwingBadInputs = [ null, undefined ]\n\ntest('with bad inputs', () => {\n throwingBadInputs.forEach(badInput => {\n expect(() => splitWhen(equals(2), badInput)).toThrowWithMessage(TypeError,\n `Cannot read property 'length' of ${ badInput }`)\n expect(() => splitWhenRamda(equals(2), badInput)).toThrowWithMessage(TypeError,\n `Cannot read properties of ${ badInput } (reading 'length')`)\n })\n\n badInputs.forEach(badInput => {\n const result = splitWhen(equals(2), badInput)\n const ramdaResult = splitWhenRamda(equals(2), badInput)\n expect(result).toEqual(ramdaResult)\n })\n})\n```\n\n \n\n\n\nTypeScript test
\n\n```typescript\nimport {splitWhen} from 'rambda'\n\nconst list = [1, 2, 1, 2]\nconst predicate = (x: number) => x === 2\n\ndescribe('R.splitWhen', () => {\n it('happy', () => {\n const result = splitWhen(predicate, list)\n\n result // $ExpectType number[][]\n })\n it('curried', () => {\n const result = splitWhen(predicate)(list)\n\n result // $ExpectType number[][]\n })\n})\n```\n\n \n\n[](#splitWhen)\n\n### startsWith\n\n```typescript\n\nstartsWith(question: T, input: string): boolean\n```\n\nWhen iterable is a string, then it behaves as `String.prototype.startsWith`.\nWhen iterable is a list, then it uses R.equals to determine if the target list starts in the same way as the given target.\n\nTry this R.startsWith example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\nstartsWith(question: T, input: string): boolean;\nstartsWith(question: T): (input: string) => boolean;\nstartsWith(question: T[], input: T[]): boolean;\nstartsWith(question: T[]): (input: T[]) => boolean;\n```\n\n \n\n\n\nR.startsWith source
\n\n```javascript\nimport { isArray } from './_internals/isArray.js'\nimport { equals } from './equals.js'\n\nexport function startsWith(question, iterable){\n if (arguments.length === 1)\n return _iterable => startsWith(question, _iterable)\n\n if (typeof iterable === 'string'){\n return iterable.startsWith(question)\n }\n if (!isArray(question)) return false\n\n let correct = true\n const filtered = question.filter((x, index) => {\n if (!correct) return false\n const result = equals(x, iterable[ index ])\n if (!result) correct = false\n\n return result\n })\n\n return filtered.length === question.length\n}\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { startsWith as startsWithRamda } from 'ramda'\n\nimport { compareCombinations } from './_internals/testUtils.js'\nimport { possibleIterables, possibleTargets } from './endsWith.spec.js'\nimport { startsWith } from './startsWith.js'\n\ntest('with string', () => {\n expect(startsWith('foo', 'foo-bar')).toBeTrue()\n expect(startsWith('baz')('foo-bar')).toBeFalse()\n})\n\ntest('use R.equals with array', () => {\n const list = [ { a : 1 }, { a : 2 }, { a : 3 } ]\n expect(startsWith({ a : 1 }, list)).toBeFalse()\n expect(startsWith([ { a : 1 } ], list)).toBeTrue()\n expect(startsWith([ { a : 1 }, { a : 2 } ], list)).toBeTrue()\n expect(startsWith(list, list)).toBeTrue()\n expect(startsWith([ { a : 2 } ], list)).toBeFalse()\n})\n\ndescribe('brute force', () => {\n compareCombinations({\n fn : startsWith,\n fnRamda : startsWithRamda,\n firstInput : possibleTargets,\n secondInput : possibleIterables,\n callback : errorsCounters => {\n expect(errorsCounters).toMatchInlineSnapshot(`\n {\n \"ERRORS_MESSAGE_MISMATCH\": 0,\n \"ERRORS_TYPE_MISMATCH\": 0,\n \"RESULTS_MISMATCH\": 0,\n \"SHOULD_NOT_THROW\": 0,\n \"SHOULD_THROW\": 0,\n \"TOTAL_TESTS\": 32,\n }\n `)\n },\n })\n})\n```\n\n \n\n\n\nTypeScript test
\n\n```typescript\nimport {startsWith} from 'rambda'\n\ndescribe('R.startsWith - array', () => {\n const question = [{a: 1}]\n const iterable = [{a: 1}, {a: 2}]\n it('happy', () => {\n const result = startsWith(question, iterable)\n result // $ExpectType boolean\n })\n it('curried', () => {\n const result = startsWith(question)(iterable)\n result // $ExpectType boolean\n })\n})\n\ndescribe('R.startsWith - string', () => {\n const question = 'foo'\n const iterable = 'foo bar'\n it('happy', () => {\n const result = startsWith(question, iterable)\n result // $ExpectType boolean\n })\n it('curried', () => {\n const result = startsWith(question)(iterable)\n result // $ExpectType boolean\n })\n})\n```\n\n \n\n[](#startsWith)\n\n### subtract\n\nCurried version of `x - y`\n\nTry this R.subtract example in Rambda REPL\n\n[](#subtract)\n\n### sum\n\n```typescript\n\nsum(list: number[]): number\n```\n\nTry this R.sum example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\nsum(list: number[]): number;\n```\n\n \n\n\n\nR.sum source
\n\n```javascript\nexport function sum(list){\n return list.reduce((prev, current) => prev + current, 0)\n}\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { sum } from './sum.js'\n\ntest('happy', () => {\n expect(sum([ 1, 2, 3, 4, 5 ])).toBe(15)\n})\n```\n\n \n\n[](#sum)\n\n### swap\n\nTry this R.swap example in Rambda REPL\n\n[](#swap)\n\n### symmetricDifference\n\n```typescript\n\nsymmetricDifference(x: T[], y: T[]): T[]\n```\n\nIt returns a merged list of `x` and `y` with all equal elements removed.\n\n`R.equals` is used to determine equality.\n\nTry this R.symmetricDifference example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\nsymmetricDifference(x: T[], y: T[]): T[];\nsymmetricDifference(x: T[]): (y: T[]) => T[];\n```\n\n \n\n\n\nR.symmetricDifference source
\n\n```javascript\nimport { concat } from './concat.js'\nimport { filter } from './filter.js'\nimport { includes } from './includes.js'\n\nexport function symmetricDifference(x, y){\n if (arguments.length === 1){\n return _y => symmetricDifference(x, _y)\n }\n\n return concat(filter(value => !includes(value, y), x),\n filter(value => !includes(value, x), y))\n}\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { symmetricDifference } from './symmetricDifference.js'\n\ntest('symmetricDifference', () => {\n const list1 = [ 1, 2, 3, 4 ]\n const list2 = [ 3, 4, 5, 6 ]\n expect(symmetricDifference(list1)(list2)).toEqual([ 1, 2, 5, 6 ])\n\n expect(symmetricDifference([], [])).toEqual([])\n})\n\ntest('symmetricDifference with objects', () => {\n const list1 = [ { id : 1 }, { id : 2 }, { id : 3 }, { id : 4 } ]\n const list2 = [ { id : 3 }, { id : 4 }, { id : 5 }, { id : 6 } ]\n expect(symmetricDifference(list1)(list2)).toEqual([\n { id : 1 },\n { id : 2 },\n { id : 5 },\n { id : 6 },\n ])\n})\n```\n\n \n\n\n\nTypeScript test
\n\n```typescript\nimport {symmetricDifference} from 'rambda'\n\ndescribe('R.symmetricDifference', () => {\n it('happy', () => {\n const list1 = [1, 2, 3, 4]\n const list2 = [3, 4, 5, 6]\n const result = symmetricDifference(list1, list2)\n\n result // $ExpectType number[]\n })\n\n it('curried', () => {\n const list1 = [{id: 1}, {id: 2}, {id: 3}, {id: 4}]\n const list2 = [{id: 3}, {id: 4}, {id: 5}, {id: 6}]\n const result = symmetricDifference(list1)(list2)\n\n result // $ExpectType { id: number; }[]\n })\n})\n```\n\n \n\n[](#symmetricDifference)\n\n### T\n\n```typescript\n\nT(): boolean\n```\n\nTry this R.T example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\nT(): boolean;\n```\n\n \n\n\n\nR.T source
\n\n```javascript\nexport function T(){\n return true\n}\n```\n\n \n\n[](#T)\n\n### tail\n\n```typescript\n\ntail(input: T): T extends [any, ...infer U] ? U : [...T]\n```\n\nIt returns all but the first element of `input`.\n\nTry this R.tail example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\ntail(input: T): T extends [any, ...infer U] ? U : [...T];\ntail(input: string): string;\n```\n\n \n\n\n\nR.tail source
\n\n```javascript\nimport { drop } from './drop.js'\n\nexport function tail(listOrString){\n return drop(1, listOrString)\n}\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { tail } from './tail.js'\n\ntest('tail', () => {\n expect(tail([ 1, 2, 3 ])).toEqual([ 2, 3 ])\n expect(tail([ 1, 2 ])).toEqual([ 2 ])\n expect(tail([ 1 ])).toEqual([])\n expect(tail([])).toEqual([])\n\n expect(tail('abc')).toBe('bc')\n expect(tail('ab')).toBe('b')\n expect(tail('a')).toBe('')\n expect(tail('')).toBe('')\n})\n```\n\n \n\n\n\nTypeScript test
\n\n```typescript\nimport {tail} from 'rambda'\n\ndescribe('R.tail', () => {\n it('with string', () => {\n const result = tail('foo')\n\n result // $ExpectType string\n })\n it('with list - one type', () => {\n const result = tail([1, 2, 3])\n\n result // $ExpectType number[]\n })\n it('with list - mixed types', () => {\n const result = tail(['foo', 'bar', 1, 2, 3])\n\n result // $ExpectType (string | number)[]\n })\n})\n```\n\n \n\n[](#tail)\n\n### take\n\n```typescript\n\ntake(howMany: number, input: T): T extends string ? string : T\n```\n\nIt returns the first `howMany` elements of `input`.\n\nTry this R.take example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\ntake(howMany: number, input: T): T extends string ? string : T;\ntake(howMany: number) : (input: T) => T extends string ? string : T;\n```\n\n \n\n\n\nR.take source
\n\n```javascript\nimport baseSlice from './_internals/baseSlice.js'\n\nexport function take(howMany, listOrString){\n if (arguments.length === 1)\n return _listOrString => take(howMany, _listOrString)\n if (howMany < 0) return listOrString.slice()\n if (typeof listOrString === 'string') return listOrString.slice(0, howMany)\n\n return baseSlice(\n listOrString, 0, howMany\n )\n}\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { take } from './take.js'\n\ntest('happy', () => {\n const arr = [ 'foo', 'bar', 'baz' ]\n\n expect(take(1, arr)).toEqual([ 'foo' ])\n\n expect(arr).toEqual([ 'foo', 'bar', 'baz' ])\n\n expect(take(2)([ 'foo', 'bar', 'baz' ])).toEqual([ 'foo', 'bar' ])\n expect(take(3, [ 'foo', 'bar', 'baz' ])).toEqual([ 'foo', 'bar', 'baz' ])\n expect(take(4, [ 'foo', 'bar', 'baz' ])).toEqual([ 'foo', 'bar', 'baz' ])\n expect(take(3)('rambda')).toBe('ram')\n})\n\ntest('with negative index', () => {\n expect(take(-1, [ 1, 2, 3 ])).toEqual([ 1, 2, 3 ])\n expect(take(-Infinity, [ 1, 2, 3 ])).toEqual([ 1, 2, 3 ])\n})\n\ntest('with zero index', () => {\n expect(take(0, [ 1, 2, 3 ])).toEqual([])\n})\n```\n\n \n\n\n\nTypeScript test
\n\n```typescript\nimport {take} from 'rambda'\n\nconst list = [1, 2, 3, 4]\nconst str = 'foobar'\nconst howMany = 2\n\ndescribe('R.take - array', () => {\n it('happy', () => {\n const result = take(howMany, list)\n\n result // $ExpectType number[]\n })\n it('curried', () => {\n const result = take(howMany)(list)\n\n result // $ExpectType number[]\n })\n})\n\ndescribe('R.take - string', () => {\n it('happy', () => {\n const result = take(howMany, str)\n\n result // $ExpectType string\n })\n it('curried', () => {\n const result = take(howMany)(str)\n\n result // $ExpectType string\n })\n})\n```\n\n \n\n[](#take)\n\n### takeLast\n\n```typescript\n\ntakeLast(howMany: number, input: T): T extends string ? string : T\n```\n\nIt returns the last `howMany` elements of `input`.\n\nTry this R.takeLast example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\ntakeLast(howMany: number, input: T): T extends string ? string : T;\ntakeLast(howMany: number) : (input: T) => T extends string ? string : T;\n```\n\n \n\n\n\nR.takeLast source
\n\n```javascript\nimport baseSlice from './_internals/baseSlice.js'\n\nexport function takeLast(howMany, listOrString){\n if (arguments.length === 1)\n return _listOrString => takeLast(howMany, _listOrString)\n\n const len = listOrString.length\n if (howMany < 0) return listOrString.slice()\n let numValue = howMany > len ? len : howMany\n\n if (typeof listOrString === 'string')\n return listOrString.slice(len - numValue)\n\n numValue = len - numValue\n\n return baseSlice(\n listOrString, numValue, len\n )\n}\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { takeLast } from './takeLast.js'\n\ntest('with arrays', () => {\n expect(takeLast(1, [ 'foo', 'bar', 'baz' ])).toEqual([ 'baz' ])\n\n expect(takeLast(2)([ 'foo', 'bar', 'baz' ])).toEqual([ 'bar', 'baz' ])\n\n expect(takeLast(3, [ 'foo', 'bar', 'baz' ])).toEqual([ 'foo', 'bar', 'baz' ])\n\n expect(takeLast(4, [ 'foo', 'bar', 'baz' ])).toEqual([ 'foo', 'bar', 'baz' ])\n\n expect(takeLast(10, [ 'foo', 'bar', 'baz' ])).toEqual([ 'foo', 'bar', 'baz' ])\n})\n\ntest('with strings', () => {\n expect(takeLast(3, 'rambda')).toBe('bda')\n\n expect(takeLast(7, 'rambda')).toBe('rambda')\n})\n\ntest('with negative index', () => {\n expect(takeLast(-1, [ 1, 2, 3 ])).toEqual([ 1, 2, 3 ])\n expect(takeLast(-Infinity, [ 1, 2, 3 ])).toEqual([ 1, 2, 3 ])\n})\n```\n\n \n\n\n\nTypeScript test
\n\n```typescript\nimport {filter, piped, takeLast} from 'rambda'\n\nconst list = [1, 2, 3, 4]\nconst str = 'foobar'\nconst howMany = 2\n\ndescribe('R.takeLast - array', () => {\n it('happy', () => {\n const result = takeLast(howMany, list)\n\n result // $ExpectType number[]\n })\n it('curried', () => {\n const result = takeLast(howMany)(list)\n\n result // $ExpectType number[]\n })\n\tit('real case', () => {\n\t\tconst data = ['foo', 'bar', 'baz', 'qux']\n\t\tconst result = piped(\n\t\t\tdata,\n\t\t\tfilter(\n\t\t\t\tx => x.length >= 100\n\t\t\t),\n\t\t\ttakeLast(2),\n\t\t)\n\t\tresult // $ExpectType string[]\n\t})\n})\n\ndescribe('R.takeLast - string', () => {\n it('happy', () => {\n const result = takeLast(howMany, str)\n\n result // $ExpectType string\n })\n it('curried', () => {\n const result = takeLast(howMany)(str)\n\n result // $ExpectType string\n })\n})\n```\n\n \n\n[](#takeLast)\n\n### takeLastWhile\n\n```typescript\n\ntakeLastWhile(predicate: (x: string) => boolean, input: string): string\n```\n\nTry this R.takeLastWhile example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\ntakeLastWhile(predicate: (x: string) => boolean, input: string): string;\ntakeLastWhile(predicate: (x: string) => boolean): (input: string) => string;\ntakeLastWhile(predicate: (x: T) => boolean, input: T[]): T[];\ntakeLastWhile(predicate: (x: T) => boolean): (input: T[]) => T[];\n```\n\n \n\n\n\nR.takeLastWhile source
\n\n```javascript\nimport { isArray } from './_internals/isArray.js'\n\nexport function takeLastWhile(predicate, input){\n if (arguments.length === 1){\n return _input => takeLastWhile(predicate, _input)\n }\n if (input.length === 0) return input\n\n const toReturn = []\n let counter = input.length\n\n while (counter){\n const item = input[ --counter ]\n if (!predicate(item)){\n break\n }\n toReturn.push(item)\n }\n\n return isArray(input) ? toReturn.reverse() : toReturn.reverse().join('')\n}\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { takeLastWhile } from './takeLastWhile.js'\nconst assert = require('assert')\n\nconst list = [ 1, 2, 3, 4 ]\n\ntest('happy', () => {\n const predicate = x => x > 2\n const result = takeLastWhile(predicate, list)\n expect(result).toEqual([ 3, 4 ])\n})\n\ntest('predicate is always true', () => {\n const predicate = () => true\n const result = takeLastWhile(predicate)(list)\n expect(result).toEqual(list)\n})\n\ntest('predicate is always false', () => {\n const predicate = () => false\n const result = takeLastWhile(predicate, list)\n expect(result).toEqual([])\n})\n\ntest('with string', () => {\n const result = takeLastWhile(x => x !== 'F', 'FOOBAR')\n expect(result).toBe('OOBAR')\n})\n```\n\n \n\n\n\nTypeScript test
\n\n```typescript\nimport {takeLastWhile} from 'rambda'\n\nconst list = [1, 2, 3]\nconst str = 'FOO'\n\ndescribe('R.takeLastWhile', () => {\n it('with array', () => {\n const result = takeLastWhile(x => x > 1, list)\n\n result // $ExpectType number[]\n })\n it('with array - curried', () => {\n const result = takeLastWhile(x => x > 1, list)\n\n result // $ExpectType number[]\n })\n it('with string', () => {\n const result = takeLastWhile(x => x !== 'F', str)\n\n result // $ExpectType string\n })\n it('with string - curried', () => {\n const result = takeLastWhile(x => x !== 'F')(str)\n\n result // $ExpectType string\n })\n})\n```\n\n \n\n[](#takeLastWhile)\n\n### takeWhile\n\nTry this R.takeWhile example in Rambda REPL\n\n[](#takeWhile)\n\n### tap\n\n```typescript\n\ntap(fn: (x: T) => void, input: T): T\n```\n\nIt applies function `fn` to input `x` and returns `x`. \n\nOne use case is debugging in the middle of `R.compose`.\n\nTry this R.tap example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\ntap(fn: (x: T) => void, input: T): T;\ntap(fn: (x: T) => void): (input: T) => T;\n```\n\n \n\n\n\nR.tap source
\n\n```javascript\nexport function tap(fn, x){\n if (arguments.length === 1) return _x => tap(fn, _x)\n\n fn(x)\n\n return x\n}\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { tap } from './tap.js'\n\ntest('tap', () => {\n let a = 1\n const sayX = x => a = x\n\n expect(tap(sayX, 100)).toBe(100)\n expect(tap(sayX)(100)).toBe(100)\n expect(a).toBe(100)\n})\n```\n\n \n\n\n\nTypeScript test
\n\n```typescript\nimport {tap, pipe} from 'rambda'\n\ndescribe('R.tap', () => {\n it('happy', () => {\n pipe(\n tap(x => {\n x // $ExpectType number[]\n }),\n (x: number[]) => x.length\n )([1, 2])\n })\n})\n```\n\n \n\n[](#tap)\n\n### test\n\n```typescript\n\ntest(regExpression: RegExp): (str: string) => boolean\n```\n\nIt determines whether `str` matches `regExpression`.\n\nTry this R.test example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\ntest(regExpression: RegExp): (str: string) => boolean;\ntest(regExpression: RegExp, str: string): boolean;\n```\n\n \n\n\n\nR.test source
\n\n```javascript\nexport function test(pattern, str){\n if (arguments.length === 1) return _str => test(pattern, _str)\n\n if (typeof pattern === 'string'){\n throw new TypeError(`R.test requires a value of type RegExp as its first argument; received \"${ pattern }\"`)\n }\n\n return str.search(pattern) !== -1\n}\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { test as testMethod } from './test.js'\n\ntest('happy', () => {\n expect(testMethod(/^x/, 'xyz')).toBeTrue()\n\n expect(testMethod(/^y/)('xyz')).toBeFalse()\n})\n\ntest('throws if first argument is not regex', () => {\n expect(() => testMethod('foo', 'bar')).toThrowErrorMatchingInlineSnapshot('\"R.test requires a value of type RegExp as its first argument; received \"foo\"\"')\n})\n```\n\n \n\n\n\nTypeScript test
\n\n```typescript\nimport {test} from 'rambda'\n\nconst input = 'foo '\nconst regex = /foo/\n\ndescribe('R.test', () => {\n it('happy', () => {\n const result = test(regex, input)\n\n result // $ExpectType boolean\n })\n it('curried', () => {\n const result = test(regex)(input)\n\n result // $ExpectType boolean\n })\n})\n```\n\n \n\n[](#test)\n\n### times\n\n```typescript\n\ntimes(fn: (i: number) => T, howMany: number): T[]\n```\n\nIt returns the result of applying function `fn` over members of range array.\n\nThe range array includes numbers between `0` and `howMany`(exclusive).\n\nTry this R.times example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\ntimes(fn: (i: number) => T, howMany: number): T[];\ntimes(fn: (i: number) => T): (howMany: number) => T[];\n```\n\n \n\n\n\nR.times source
\n\n```javascript\nimport { isInteger } from './_internals/isInteger.js'\nimport { map } from './map.js'\nimport { range } from './range.js'\n\nexport function times(fn, howMany){\n if (arguments.length === 1) return _howMany => times(fn, _howMany)\n if (!isInteger(howMany) || howMany < 0){\n throw new RangeError('n must be an integer')\n }\n\n return map(fn, range(0, howMany))\n}\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport assert from 'assert'\n\nimport { identity } from './identity.js'\nimport { times } from './times.js'\n\ntest('happy', () => {\n const result = times(identity, 5)\n\n expect(result).toEqual([ 0, 1, 2, 3, 4 ])\n})\n\ntest('with bad input', () => {\n assert.throws(() => {\n times(3)('cheers!')\n }, RangeError)\n assert.throws(() => {\n times(identity, -1)\n }, RangeError)\n})\n\ntest('curry', () => {\n const result = times(identity)(5)\n\n expect(result).toEqual([ 0, 1, 2, 3, 4 ])\n})\n```\n\n \n\n\n\nTypeScript test
\n\n```typescript\nimport {times, identity} from 'rambda'\n\ndescribe('R.times', () => {\n it('happy', () => {\n const result = times(identity, 5)\n result // $ExpectType number[]\n })\n})\n```\n\n \n\n[](#times)\n\n### toLower\n\n```typescript\n\ntoLower(str: S): Lowercase\n```\n\nTry this R.toLower example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\ntoLower(str: S): Lowercase;\ntoLower(str: string): string;\n```\n\n \n\n\n\nR.toLower source
\n\n```javascript\nexport function toLower(str){\n return str.toLowerCase()\n}\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { toLower } from './toLower.js'\n\ntest('toLower', () => {\n expect(toLower('FOO|BAR|BAZ')).toBe('foo|bar|baz')\n})\n```\n\n \n\n[](#toLower)\n\n### toPairs\n\n```typescript\n\ntoPairs>(obj: O): Array<{ [key in K]: [`${key}`, O[key]] }[K]>\n```\n\nIt transforms an object to a list.\n\nTry this R.toPairs example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\ntoPairs>(obj: O): Array<{ [key in K]: [`${key}`, O[key]] }[K]>;\ntoPairs(obj: Record): Array<[string, S]>;\n```\n\n \n\n\n\nR.toPairs source
\n\n```javascript\nexport function toPairs(obj){\n return Object.entries(obj)\n}\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { toPairs } from './toPairs.js'\n\nconst obj = {\n a : 1,\n b : 2,\n c : [ 3, 4 ],\n}\nconst expected = [\n [ 'a', 1 ],\n [ 'b', 2 ],\n [ 'c', [ 3, 4 ] ],\n]\n\ntest('happy', () => {\n expect(toPairs(obj)).toEqual(expected)\n})\n```\n\n \n\n[](#toPairs)\n\n### toString\n\n```typescript\n\ntoString(x: unknown): string\n```\n\nTry this R.toString example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\ntoString(x: unknown): string;\n```\n\n \n\n\n\nR.toString source
\n\n```javascript\nexport function toString(x){\n return x.toString()\n}\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { toString } from './toString.js'\n\ntest('happy', () => {\n expect(toString([ 1, 2, 3 ])).toBe('1,2,3')\n})\n```\n\n \n\n[](#toString)\n\n### toUpper\n\n```typescript\n\ntoUpper(str: S): Uppercase\n```\n\nTry this R.toUpper example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\ntoUpper(str: S): Uppercase;\ntoUpper(str: string): string;\n```\n\n \n\n\n\nR.toUpper source
\n\n```javascript\nexport function toUpper(str){\n return str.toUpperCase()\n}\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { toUpper } from './toUpper.js'\n\ntest('toUpper', () => {\n expect(toUpper('foo|bar|baz')).toBe('FOO|BAR|BAZ')\n})\n```\n\n \n\n[](#toUpper)\n\n### transpose\n\n```typescript\n\ntranspose(list: (T[])[]): (T[])[]\n```\n\nTry this R.transpose example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\ntranspose(list: (T[])[]): (T[])[];\n```\n\n \n\n\n\nR.transpose source
\n\n```javascript\nimport { isArray } from './_internals/isArray.js'\n\nexport function transpose(array){\n return array.reduce((acc, el) => {\n el.forEach((nestedEl, i) =>\n isArray(acc[ i ]) ? acc[ i ].push(nestedEl) : acc.push([ nestedEl ]))\n\n return acc\n }, [])\n}\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { transpose } from './transpose.js'\n\ntest('happy', () => {\n const input = [\n [ 'a', 1 ],\n [ 'b', 2 ],\n [ 'c', 3 ],\n ]\n\n expect(transpose(input)).toEqual([\n [ 'a', 'b', 'c' ],\n [ 1, 2, 3 ],\n ])\n})\n\ntest('when rows are shorter', () => {\n const actual = transpose([ [ 10, 11 ], [ 20 ], [], [ 30, 31, 32 ] ])\n const expected = [ [ 10, 20, 30 ], [ 11, 31 ], [ 32 ] ]\n expect(actual).toEqual(expected)\n})\n\ntest('with empty array', () => {\n expect(transpose([])).toEqual([])\n})\n\ntest('array with falsy values', () => {\n const actual = transpose([\n [ true, false, undefined, null ],\n [ null, undefined, false, true ],\n ])\n const expected = [\n [ true, null ],\n [ false, undefined ],\n [ undefined, false ],\n [ null, true ],\n ]\n expect(actual).toEqual(expected)\n})\n```\n\n \n\n\n\nTypeScript test
\n\n```typescript\nimport {transpose} from 'rambda'\n\nconst input = [\n ['a', 1],\n ['b', 2],\n ['c', 3],\n]\n\ndescribe('R.transpose', () => {\n it('happy', () => {\n const result = transpose(input)\n\n result // $ExpectType (string | number)[][]\n })\n})\n```\n\n \n\n[](#transpose)\n\n### trim\n\n```typescript\n\ntrim(str: string): string\n```\n\nTry this R.trim example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\ntrim(str: string): string;\n```\n\n \n\n\n\nR.trim source
\n\n```javascript\nexport function trim(str){\n return str.trim()\n}\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { trim } from './trim.js'\n\ntest('trim', () => {\n expect(trim(' foo ')).toBe('foo')\n})\n```\n\n \n\n[](#trim)\n\n### tryCatch\n\nIt returns function that runs `fn` in `try/catch` block. If there was an error, then `fallback` is used to return the result. Note that `fn` can be value or asynchronous/synchronous function(unlike `Ramda` where fallback can only be a synchronous function).\n\nTry this R.tryCatch example in Rambda REPL\n\n[](#tryCatch)\n\n### type\n\nIt accepts any input and it returns its type.\n\nTry this R.type example in Rambda REPL\n\n[](#type)\n\n### unapply\n\n```typescript\n\nunapply(fn: (args: any[]) => T): (...args: any[]) => T\n```\n\nIt calls a function `fn` with the list of values of the returned function. \n\n`R.unapply` is the opposite of `R.apply` method.\n\nTry this R.unapply example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\nunapply(fn: (args: any[]) => T): (...args: any[]) => T;\n```\n\n \n\n\n\nR.unapply source
\n\n```javascript\nexport function unapply(fn){\n return function (...args){\n return fn.call(this, args)\n }\n}\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { apply } from './apply.js'\nimport { converge } from './converge.js'\nimport { identity } from './identity.js'\nimport { prop } from './prop.js'\nimport { sum } from './sum.js'\nimport { unapply } from './unapply.js'\n\ntest('happy', () => {\n const fn = unapply(identity)\n expect(fn(\n 1, 2, 3\n )).toEqual([ 1, 2, 3 ])\n expect(fn()).toEqual([])\n})\n\ntest('returns a function which is always passed one argument', () => {\n const fn = unapply(function (){\n return arguments.length\n })\n expect(fn('x')).toBe(1)\n expect(fn('x', 'y')).toBe(1)\n expect(fn(\n 'x', 'y', 'z'\n )).toBe(1)\n})\n\ntest('forwards arguments to decorated function as an array', () => {\n const fn = unapply(xs => '[' + xs + ']')\n expect(fn(2)).toBe('[2]')\n expect(fn(2, 4)).toBe('[2,4]')\n expect(fn(\n 2, 4, 6\n )).toBe('[2,4,6]')\n})\n\ntest('returns a function with length 0', () => {\n const fn = unapply(identity)\n expect(fn).toHaveLength(0)\n})\n\ntest('is the inverse of R.apply', () => {\n let a, b, c, d, e, f, g, n\n const rand = function (){\n return Math.floor(200 * Math.random()) - 100\n }\n\n f = Math.max\n g = unapply(apply(f))\n n = 1\n while (n <= 100){\n a = rand()\n b = rand()\n c = rand()\n d = rand()\n e = rand()\n expect(f(\n a, b, c, d, e\n )).toEqual(g(\n a, b, c, d, e\n ))\n n += 1\n }\n\n f = function (xs){\n return '[' + xs + ']'\n }\n g = apply(unapply(f))\n n = 1\n while (n <= 100){\n a = rand()\n b = rand()\n c = rand()\n d = rand()\n e = rand()\n expect(f([ a, b, c, d, e ])).toEqual(g([ a, b, c, d, e ]))\n n += 1\n }\n})\n\ntest('it works with converge', () => {\n const fn = unapply(sum)\n const convergeFn = converge(fn, [ prop('a'), prop('b'), prop('c') ])\n const obj = {\n a : 1337,\n b : 42,\n c : 1,\n }\n const expected = 1337 + 42 + 1\n expect(convergeFn(obj)).toEqual(expected)\n})\n```\n\n \n\n\n\nTypeScript test
\n\n```typescript\nimport {join, unapply, sum} from 'rambda'\n\ndescribe('R.unapply', () => {\n it('happy', () => {\n const fn = unapply(sum)\n\n fn(1, 2, 3) // $ExpectType number\n })\n\n it('joins a string', () => {\n const fn = unapply(join(''))\n\n fn('s', 't', 'r', 'i', 'n', 'g') // $ExpectType string\n })\n})\n```\n\n \n\n[](#unapply)\n\n### union\n\n```typescript\n\nunion(x: T[], y: T[]): T[]\n```\n\nIt takes two lists and return a new list containing a merger of both list with removed duplicates. \n\n`R.equals` is used to compare for duplication.\n\nTry this R.union example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\nunion(x: T[], y: T[]): T[];\nunion(x: T[]): (y: T[]) => T[];\n```\n\n \n\n\n\nR.union source
\n\n```javascript\nimport { cloneList } from './_internals/cloneList.js'\nimport { includes } from './includes.js'\n\nexport function union(x, y){\n if (arguments.length === 1) return _y => union(x, _y)\n\n const toReturn = cloneList(x)\n\n y.forEach(yInstance => {\n if (!includes(yInstance, x)) toReturn.push(yInstance)\n })\n\n return toReturn\n}\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { union } from './union.js'\n\ntest('happy', () => {\n expect(union([ 1, 2 ], [ 2, 3 ])).toEqual([ 1, 2, 3 ])\n})\n\ntest('with list of objects', () => {\n const list1 = [ { a : 1 }, { a : 2 } ]\n const list2 = [ { a : 2 }, { a : 3 } ]\n const result = union(list1)(list2)\n})\n```\n\n \n\n\n\nTypeScript test
\n\n```typescript\nimport {union} from 'rambda'\n\ndescribe('R.union', () => {\n it('happy', () => {\n const result = union([1, 2], [2, 3])\n\n result // $ExpectType number[]\n })\n it('with array of objects - case 1', () => {\n const list1 = [{a: 1}, {a: 2}]\n const list2 = [{a: 2}, {a: 3}]\n const result = union(list1, list2)\n result // $ExpectType { a: number; }[]\n })\n it('with array of objects - case 2', () => {\n const list1 = [{a: 1, b: 1}, {a: 2}]\n const list2 = [{a: 2}, {a: 3, b: 3}]\n const result = union(list1, list2)\n result[0].a // $ExpectType number\n result[0].b // $ExpectType number | undefined\n })\n})\n\ndescribe('R.union - curried', () => {\n it('happy', () => {\n const result = union([1, 2])([2, 3])\n\n result // $ExpectType number[]\n })\n it('with array of objects - case 1', () => {\n const list1 = [{a: 1}, {a: 2}]\n const list2 = [{a: 2}, {a: 3}]\n const result = union(list1)(list2)\n result // $ExpectType { a: number; }[]\n })\n it('with array of objects - case 2', () => {\n const list1 = [{a: 1, b: 1}, {a: 2}]\n const list2 = [{a: 2}, {a: 3, b: 3}]\n const result = union(list1)(list2)\n result[0].a // $ExpectType number\n result[0].b // $ExpectType number | undefined\n })\n})\n```\n\n \n\n[](#union)\n\n### uniq\n\n```typescript\n\nuniq(list: T[]): T[]\n```\n\nIt returns a new array containing only one copy of each element of `list`.\n\n`R.equals` is used to determine equality.\n\nTry this R.uniq example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\nuniq(list: T[]): T[];\n```\n\n \n\n\n\nR.uniq source
\n\n```javascript\nimport { _Set } from './_internals/set.js'\n\nexport function uniq(list){\n const set = new _Set()\n const willReturn = []\n list.forEach(item => {\n if (set.checkUniqueness(item)){\n willReturn.push(item)\n }\n })\n\n return willReturn\n}\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { uniq } from './uniq.js'\n\ntest('happy', () => {\n const list = [ 1, 2, 3, 3, 3, 1, 2, 0 ]\n expect(uniq(list)).toEqual([ 1, 2, 3, 0 ])\n})\n\ntest('with object', () => {\n const list = [ { a : 1 }, { a : 2 }, { a : 1 }, { a : 2 } ]\n expect(uniq(list)).toEqual([ { a : 1 }, { a : 2 } ])\n})\n\ntest('with nested array', () => {\n expect(uniq([ [ 42 ], [ 42 ] ])).toEqual([ [ 42 ] ])\n})\n\ntest('with booleans', () => {\n expect(uniq([ [ false ], [ false ], [ true ] ])).toEqual([ [ false ], [ true ] ])\n})\n\ntest('with falsy values', () => {\n expect(uniq([ undefined, null ])).toEqual([ undefined, null ])\n})\n\ntest('can distinct between string and number', () => {\n expect(uniq([ 1, '1' ])).toEqual([ 1, '1' ])\n})\n```\n\n \n\n\n\nTypeScript test
\n\n```typescript\nimport {uniq} from 'rambda'\n\ndescribe('R.uniq', () => {\n it('happy', () => {\n const result = uniq([1, 2, 3, 3, 3, 1, 2, 0])\n result // $ExpectType number[]\n })\n})\n```\n\n \n\n[](#uniq)\n\n### uniqBy\n\nIt applies uniqueness to input list based on function that defines what to be used for comparison between elements.\n\n`R.equals` is used to determine equality.\n\nTry this R.uniqBy example in Rambda REPL\n\n[](#uniqBy)\n\n### uniqWith\n\n```typescript\n\nuniqWith(predicate: (x: T, y: T) => boolean, list: T[]): T[]\n```\n\nIt returns a new array containing only one copy of each element in `list` according to `predicate` function.\n\nThis predicate should return true, if two elements are equal.\n\nTry this R.uniqWith example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\nuniqWith(predicate: (x: T, y: T) => boolean, list: T[]): T[];\nuniqWith(predicate: (x: T, y: T) => boolean): (list: T[]) => T[];\n```\n\n \n\n\n\nR.uniqWith source
\n\n```javascript\nfunction includesWith(\n predicate, target, list\n){\n let willReturn = false\n let index = -1\n\n while (++index < list.length && !willReturn){\n const value = list[ index ]\n\n if (predicate(target, value)){\n willReturn = true\n }\n }\n\n return willReturn\n}\n\nexport function uniqWith(predicate, list){\n if (arguments.length === 1) return _list => uniqWith(predicate, _list)\n\n let index = -1\n const willReturn = []\n\n while (++index < list.length){\n const value = list[ index ]\n\n if (!includesWith(\n predicate, value, willReturn\n )){\n willReturn.push(value)\n }\n }\n\n return willReturn\n}\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { uniqWith as uniqWithRamda } from 'ramda'\n\nimport { uniqWith } from './uniqWith.js'\n\nconst list = [ { a : 1 }, { a : 1 } ]\n\ntest('happy', () => {\n const fn = (x, y) => x.a === y.a\n\n const result = uniqWith(fn, list)\n expect(result).toEqual([ { a : 1 } ])\n})\n\ntest('with list of strings', () => {\n const fn = (x, y) => x.length === y.length\n const list = [ '0', '11', '222', '33', '4', '55' ]\n const result = uniqWith(fn)(list)\n const resultRamda = uniqWithRamda(fn, list)\n expect(result).toEqual([ '0', '11', '222' ])\n expect(resultRamda).toEqual([ '0', '11', '222' ])\n})\n```\n\n \n\n\n\nTypeScript test
\n\n```typescript\nimport {uniqWith} from 'rambda'\n\ndescribe('R.uniqWith', () => {\n it('happy', () => {\n const list = [{a: 1}, {a: 1}]\n\n const fn = (x: any, y: any) => x.a === y.a\n\n const result = uniqWith(fn, list)\n result // $ExpectType { a: number; }[]\n })\n})\n```\n\n \n\n[](#uniqWith)\n\n### unless\n\n```typescript\n\nunless(predicate: (x: T) => boolean, whenFalseFn: (x: T) => U, x: T): T | U\n```\n\nThe method returns function that will be called with argument `input`.\n\nIf `predicate(input)` returns `false`, then the end result will be the outcome of `whenFalse(input)`.\n\nIn the other case, the final output will be the `input` itself.\n\nTry this R.unless example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\nunless(predicate: (x: T) => boolean, whenFalseFn: (x: T) => U, x: T): T | U;\nunless(predicate: (x: T) => boolean, whenFalseFn: (x: T) => U): (x: T) => T | U;\nunless(predicate: (x: T) => boolean, whenFalseFn: (x: T) => T, x: T): T;\nunless(predicate: (x: T) => boolean, whenFalseFn: (x: T) => T): (x: T) => T;\n```\n\n \n\n\n\nR.unless source
\n\n```javascript\nimport { curry } from './curry.js'\n\nfunction unlessFn(\n predicate, whenFalseFn, input\n){\n if (predicate(input)) return input\n\n return whenFalseFn(input)\n}\n\nexport const unless = curry(unlessFn)\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { inc } from './inc.js'\nimport { isNil } from './isNil.js'\nimport { unless } from './unless.js'\n\ntest('happy', () => {\n const safeInc = unless(isNil, inc)\n expect(safeInc(null)).toBeNull()\n expect(safeInc(1)).toBe(2)\n})\n\ntest('curried', () => {\n const safeIncCurried = unless(isNil)(inc)\n expect(safeIncCurried(null)).toBeNull()\n})\n\ntest('with 3 inputs', () => {\n let result = unless(x => x.startsWith('/'), x=> x.concat('/'), '/api')\n expect(result).toBe('/api')\n})\n```\n\n \n\n\n\nTypeScript test
\n\n```typescript\nimport {unless, inc} from 'rambda'\n\ndescribe('R.unless', () => {\n it('happy', () => {\n const fn = unless(x => x > 5, inc)\n const result = fn(1)\n result // $ExpectType number\n })\n it('with one explicit type', () => {\n const result = unless(\n x => {\n x // $ExpectType number\n return x > 5\n },\n x => {\n x // $ExpectType number\n return x + 1\n },\n 1\n )\n result // $ExpectType number\n })\n it('with two different explicit types', () => {\n const result = unless(\n x => {\n x // $ExpectType number\n return x > 5\n },\n x => {\n x // $ExpectType number\n return `${x}-foo`\n },\n 1\n )\n result // $ExpectType string | number\n })\n})\n\ndescribe('R.unless - curried', () => {\n it('happy', () => {\n const fn = unless(x => x > 5, inc)\n const result = fn(1)\n result // $ExpectType number\n })\n it('with one explicit type', () => {\n const fn = unless(\n x => {\n x // $ExpectType number\n return x > 5\n },\n x => {\n x // $ExpectType number\n return x + 1\n }\n )\n const result = fn(1)\n result // $ExpectType number\n })\n it('with two different explicit types', () => {\n const fn = unless(\n x => {\n x // $ExpectType number\n return x > 5\n },\n x => {\n x // $ExpectType number\n return `${x}-foo`\n }\n )\n const result = fn(1)\n result // $ExpectType string | number\n })\n})\n```\n\n \n\n[](#unless)\n\n### unnest\n\nTry this R.unnest example in Rambda REPL\n\n[](#unnest)\n\n### unwind\n\nTry this R.unwind example in Rambda REPL\n\n[](#unwind)\n\n### update\n\n```typescript\n\nupdate(index: number, newValue: T, list: T[]): T[]\n```\n\nIt returns a copy of `list` with updated element at `index` with `newValue`.\n\nTry this R.update example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\nupdate(index: number, newValue: T, list: T[]): T[];\nupdate(index: number, newValue: T): (list: T[]) => T[];\n```\n\n \n\n\n\nR.update source
\n\n```javascript\nimport { cloneList } from './_internals/cloneList.js'\nimport { curry } from './curry.js'\n\nexport function updateFn(\n index, newValue, list\n){\n const clone = cloneList(list)\n if (index === -1) return clone.fill(newValue, index)\n\n return clone.fill(\n newValue, index, index + 1\n )\n}\n\nexport const update = curry(updateFn)\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { update } from './update.js'\n\nconst list = [ 1, 2, 3 ]\n\ntest('happy', () => {\n const newValue = 8\n const index = 1\n const result = update(\n index, newValue, list\n )\n const curriedResult = update(index, newValue)(list)\n const tripleCurriedResult = update(index)(newValue)(list)\n\n const expected = [ 1, 8, 3 ]\n expect(result).toEqual(expected)\n expect(curriedResult).toEqual(expected)\n expect(tripleCurriedResult).toEqual(expected)\n})\n\ntest('list has no such index', () => {\n const newValue = 8\n const index = 10\n const result = update(\n index, newValue, list\n )\n\n expect(result).toEqual(list)\n})\n\ntest('with negative index', () => {\n expect(update(\n -1, 10, [ 1 ]\n )).toEqual([ 10 ])\n expect(update(\n -1, 10, []\n )).toEqual([])\n expect(update(\n -1, 10, list\n )).toEqual([ 1, 2, 10 ])\n expect(update(\n -2, 10, list\n )).toEqual([ 1, 10, 3 ])\n expect(update(\n -3, 10, list\n )).toEqual([ 10, 2, 3 ])\n})\n```\n\n \n\n\n\nTypeScript test
\n\n```typescript\nimport {update} from 'rambda'\n\ndescribe('R.update', () => {\n it('happy', () => {\n const result = update(1, 0, [1, 2, 3])\n result // $ExpectType number[]\n })\n})\n```\n\n \n\n[](#update)\n\n### values\n\n```typescript\n\nvalues(obj: T): T[K][]\n```\n\nWith correct input, this is nothing more than `Object.values(Record)`. If `obj` is not an object, then it returns an empty array.\n\nTry this R.values example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\nvalues(obj: T): T[K][];\n```\n\n \n\n\n\nR.values source
\n\n```javascript\nimport { type } from './type.js'\n\nexport function values(obj){\n if (type(obj) !== 'Object') return []\n return Object.values(obj)\n}\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { values } from './values.js'\n\ntest('happy', () => {\n expect(values({\n a : 1,\n b : 2,\n c : 3,\n })).toEqual([ 1, 2, 3 ])\n})\n\ntest('with bad input', () => {\n expect(values(null)).toEqual([])\n expect(values(undefined)).toEqual([])\n expect(values(55)).toEqual([])\n expect(values('foo')).toEqual([])\n expect(values(true)).toEqual([])\n expect(values(false)).toEqual([])\n expect(values(NaN)).toEqual([])\n expect(values(Infinity)).toEqual([])\n expect(values([])).toEqual([])\n})\n```\n\n \n\n\n\nTypeScript test
\n\n```typescript\nimport {values} from 'rambda'\n\ndescribe('R.values', () => {\n it('happy', () => {\n const result = values({\n a: 1,\n b: 2,\n c: 3,\n })\n result // $ExpectType number[]\n })\n})\n```\n\n \n\n[](#values)\n\n### view\n\n```typescript\n\nview(lens: Lens): (obj: S) => A\n```\n\nIt returns the value of `lens` focus over `target` object.\n\nTry this R.view example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\nview(lens: Lens): (obj: S) => A;\nview(lens: Lens, obj: S): A;\n```\n\n \n\n\n\nR.view source
\n\n```javascript\nconst Const = x => ({\n x,\n map : fn => Const(x),\n})\n\nexport function view(lens, target){\n if (arguments.length === 1) return _target => view(lens, _target)\n\n return lens(Const)(target).x\n}\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { assoc } from './assoc.js'\nimport { lens } from './lens.js'\nimport { prop } from './prop.js'\nimport { view } from './view.js'\n\nconst testObject = { foo : 'Led Zeppelin' }\nconst assocLens = lens(prop('foo'), assoc('foo'))\n\ntest('happy', () => {\n expect(view(assocLens, testObject)).toBe('Led Zeppelin')\n})\n```\n\n \n\n[](#view)\n\n### when\n\n```typescript\n\nwhen(predicate: (x: T) => boolean, whenTrueFn: (a: T) => U, input: T): T | U\n```\n\nIt pass `input` to `predicate` function and if the result is `true`, it will return the result of `whenTrueFn(input)`. \nIf the `predicate` returns `false`, then it will simply return `input`.\n\nTry this R.when example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\nwhen(predicate: (x: T) => boolean, whenTrueFn: (a: T) => U, input: T): T | U;\nwhen(predicate: (x: T) => boolean, whenTrueFn: (a: T) => U): (input: T) => T | U;\nwhen(predicate: (x: T) => boolean): ((whenTrueFn: (a: T) => U) => (input: T) => T | U);\n```\n\n \n\n\n\nR.when source
\n\n```javascript\nimport { curry } from './curry.js'\n\nfunction whenFn(\n predicate, whenTrueFn, input\n){\n if (!predicate(input)) return input\n\n return whenTrueFn(input)\n}\n\nexport const when = curry(whenFn)\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { add } from './add.js'\nimport { when } from './when.js'\n\nconst predicate = x => typeof x === 'number'\n\ntest('happy', () => {\n const fn = when(predicate, add(11))\n expect(fn(11)).toBe(22)\n expect(fn('foo')).toBe('foo')\n})\n```\n\n \n\n\n\nTypeScript test
\n\n```typescript\nimport {when} from 'rambda'\n\nconst predicate = (x: number) => x > 2\nconst whenTrueFn = (x: number) => String(x)\n\ndescribe('R.when', () => {\n it('happy', () => {\n const result = when(predicate, whenTrueFn, 1)\n result // $ExpectType string | 1\n })\n\n it('curry 1', () => {\n const fn = when(predicate, whenTrueFn)\n const result = fn(1)\n result // $ExpectType string | number\n })\n\n it('curry 2 require explicit types', () => {\n const fn = when(predicate)(whenTrueFn)\n const result = fn(1)\n result // $ExpectType string | number\n })\n})\n```\n\n \n\n[](#when)\n\n### where\n\n```typescript\n\nwhere(conditions: T, input: U): boolean\n```\n\nIt returns `true` if all each property in `conditions` returns `true` when applied to corresponding property in `input` object.\n\nTry this R.where example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\nwhere(conditions: T, input: U): boolean;\nwhere(conditions: T): (input: U) => boolean;\nwhere(conditions: ObjFunc2, input: U): boolean;\nwhere(conditions: ObjFunc2): (input: U) => boolean;\n```\n\n \n\n\n\nR.where source
\n\n```javascript\nexport function where(conditions, input){\n if (input === undefined){\n return _input => where(conditions, _input)\n }\n let flag = true\n for (const prop in conditions){\n if (!flag) continue\n const result = conditions[ prop ](input[ prop ])\n if (flag && result === false){\n flag = false\n }\n }\n\n return flag\n}\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { equals } from './equals.js'\nimport { where } from './where.js'\n\ntest('when true', () => {\n const result = where({\n a : equals('foo'),\n b : equals('bar'),\n },\n {\n a : 'foo',\n b : 'bar',\n x : 11,\n y : 19,\n })\n\n expect(result).toBeTrue()\n})\n\ntest('when false | early exit', () => {\n let counter = 0\n const equalsFn = expected => input => {\n console.log(expected, 'expected')\n counter++\n\n return input === expected\n }\n const predicate = where({\n a : equalsFn('foo'),\n b : equalsFn('baz'),\n })\n expect(predicate({\n a : 'notfoo',\n b : 'notbar',\n })).toBeFalse()\n expect(counter).toBe(1)\n})\n```\n\n \n\n\n\nTypeScript test
\n\n```typescript\nimport {where, equals} from 'rambda'\n\ndescribe('R.where', () => {\n it('happy', () => {\n const input = {\n a: 'foo',\n b: 'bar',\n x: 11,\n y: 19,\n }\n const conditions = {\n a: equals('foo'),\n b: equals('bar'),\n }\n const result = where(conditions, input)\n const curriedResult = where(conditions)(input)\n result // $ExpectType boolean\n curriedResult // $ExpectType boolean\n })\n})\n```\n\n \n\n[](#where)\n\n### whereAny\n\nSame as `R.where`, but it will return `true` if at least one condition check returns `true`.\n\nTry this R.whereAny example in Rambda REPL\n\n[](#whereAny)\n\n### whereEq\n\n```typescript\n\nwhereEq(condition: T, input: U): boolean\n```\n\nIt will return `true` if all of `input` object fully or partially include `rule` object.\n\n`R.equals` is used to determine equality.\n\nTry this R.whereEq example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\nwhereEq(condition: T, input: U): boolean;\nwhereEq(condition: T): (input: U) => boolean;\n```\n\n \n\n\n\nR.whereEq source
\n\n```javascript\nimport { equals } from './equals.js'\nimport { filter } from './filter.js'\n\nexport function whereEq(condition, input){\n if (arguments.length === 1){\n return _input => whereEq(condition, _input)\n }\n\n const result = filter((conditionValue, conditionProp) =>\n equals(conditionValue, input[ conditionProp ]),\n condition)\n\n return Object.keys(result).length === Object.keys(condition).length\n}\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { whereEq } from './whereEq.js'\n\ntest('when true', () => {\n const condition = { a : 1 }\n const input = {\n a : 1,\n b : 2,\n }\n\n const result = whereEq(condition, input)\n const expectedResult = true\n\n expect(result).toEqual(expectedResult)\n})\n\ntest('when false', () => {\n const condition = { a : 1 }\n const input = { b : 2 }\n\n const result = whereEq(condition, input)\n const expectedResult = false\n\n expect(result).toEqual(expectedResult)\n})\n\ntest('with nested object', () => {\n const condition = { a : { b : 1 } }\n const input = {\n a : { b : 1 },\n c : 2,\n }\n\n const result = whereEq(condition)(input)\n const expectedResult = true\n\n expect(result).toEqual(expectedResult)\n})\n\ntest('with wrong input', () => {\n const condition = { a : { b : 1 } }\n\n expect(() => whereEq(condition, null)).toThrowErrorMatchingInlineSnapshot('\"Cannot read properties of null (reading \\'a\\')\"')\n})\n```\n\n \n\n\n\nTypeScript test
\n\n```typescript\nimport {whereEq} from 'rambda'\n\ndescribe('R.whereEq', () => {\n it('happy', () => {\n const result = whereEq({a: {b: 2}}, {b: 2})\n const curriedResult = whereEq({a: {b: 2}})({b: 2})\n result // $ExpectType boolean\n curriedResult // $ExpectType boolean\n })\n})\n```\n\n \n\n[](#whereEq)\n\n### without\n\n```typescript\n\nwithout(matchAgainst: T[], source: T[]): T[]\n```\n\nIt will return a new array, based on all members of `source` list that are not part of `matchAgainst` list.\n\n`R.equals` is used to determine equality.\n\nTry this R.without example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\nwithout(matchAgainst: T[], source: T[]): T[];\nwithout(matchAgainst: T[]): (source: T[]) => T[];\n```\n\n \n\n\n\nR.without source
\n\n```javascript\nimport { _indexOf } from './equals.js'\nimport { reduce } from './reduce.js'\n\nexport function without(matchAgainst, source){\n if (source === undefined){\n return _source => without(matchAgainst, _source)\n }\n\n return reduce(\n (prev, current) =>\n _indexOf(current, matchAgainst) > -1 ? prev : prev.concat(current),\n [],\n source\n )\n}\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { without as withoutRamda } from 'ramda'\n\nimport { without } from './without.js'\n\ntest('should return a new list without values in the first argument', () => {\n const itemsToOmit = [ 'A', 'B', 'C' ]\n const collection = [ 'A', 'B', 'C', 'D', 'E', 'F' ]\n\n expect(without(itemsToOmit, collection)).toEqual([ 'D', 'E', 'F' ])\n expect(without(itemsToOmit)(collection)).toEqual([ 'D', 'E', 'F' ])\n})\n\ntest('with list of objects', () => {\n const itemsToOmit = [ { a : 1 }, { c : 3 } ]\n const collection = [ { a : 1 }, { b : 2 }, { c : 3 }, { d : 4 } ]\n const expected = [ { b : 2 }, { d : 4 } ]\n\n expect(without(itemsToOmit, collection)).toEqual(expected)\n expect(withoutRamda(itemsToOmit, collection)).toEqual(expected)\n})\n\ntest('ramda accepts string as target input while rambda throws', () => {\n expect(withoutRamda('0:1', [ '0', '0:1' ])).toEqual([ '0:1' ])\n expect(() =>\n without('0:1', [ '0', '0:1' ])).toThrowErrorMatchingInlineSnapshot('\"Cannot read property \\'indexOf\\' of 0:1\"')\n expect(without([ '0:1' ], [ '0', '0:1' ])).toEqual([ '0' ])\n})\n\ntest('ramda test', () => {\n expect(without([ 1, 2 ])([ 1, 2, 1, 3, 4 ])).toEqual([ 3, 4 ])\n})\n```\n\n \n\n\n\nTypeScript test
\n\n```typescript\nimport {without} from 'rambda'\n\nconst itemsToOmit = ['A', 'B', 'C']\nconst collection = ['A', 'B', 'C', 'D', 'E', 'F']\n\ndescribe('R.without', () => {\n it('happy', () => {\n const result = without(itemsToOmit, collection)\n\n result // $ExpectType string[]\n })\n it('curried', () => {\n const result = without(itemsToOmit)(collection)\n\n result // $ExpectType string[]\n })\n})\n```\n\n \n\n[](#without)\n\n### xor\n\n```typescript\n\nxor(x: boolean, y: boolean): boolean\n```\n\nLogical XOR\n\nTry this R.xor example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\nxor(x: boolean, y: boolean): boolean;\nxor(y: boolean): (y: boolean) => boolean;\n```\n\n \n\n\n\nR.xor source
\n\n```javascript\nexport function xor(a, b){\n if (arguments.length === 1) return _b => xor(a, _b)\n\n return Boolean(a) && !b || Boolean(b) && !a\n}\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { xor } from './xor.js'\n\ntest('compares two values with exclusive or', () => {\n expect(xor(true, true)).toBeFalse()\n expect(xor(true, false)).toBeTrue()\n expect(xor(false, true)).toBeTrue()\n expect(xor(false, false)).toBeFalse()\n})\n\ntest('when both values are truthy, it should return false', () => {\n expect(xor(true, 'foo')).toBeFalse()\n expect(xor(42, true)).toBeFalse()\n expect(xor('foo', 42)).toBeFalse()\n expect(xor({}, true)).toBeFalse()\n expect(xor(true, [])).toBeFalse()\n expect(xor([], {})).toBeFalse()\n expect(xor(new Date(), true)).toBeFalse()\n expect(xor(true, Infinity)).toBeFalse()\n expect(xor(Infinity, new Date())).toBeFalse()\n})\n\ntest('when both values are falsy, it should return false', () => {\n expect(xor(null, false)).toBeFalse()\n expect(xor(false, undefined)).toBeFalse()\n expect(xor(undefined, null)).toBeFalse()\n expect(xor(0, false)).toBeFalse()\n expect(xor(false, NaN)).toBeFalse()\n expect(xor(NaN, 0)).toBeFalse()\n expect(xor('', false)).toBeFalse()\n})\n\ntest('when one argument is truthy and the other is falsy, it should return true', () => {\n expect(xor('foo', null)).toBeTrue()\n expect(xor(null, 'foo')).toBeTrue()\n expect(xor(undefined, 42)).toBeTrue()\n expect(xor(42, undefined)).toBeTrue()\n expect(xor(Infinity, NaN)).toBeTrue()\n expect(xor(NaN, Infinity)).toBeTrue()\n expect(xor({}, '')).toBeTrue()\n expect(xor('', {})).toBeTrue()\n expect(xor(new Date(), 0)).toBeTrue()\n expect(xor(0, new Date())).toBeTrue()\n expect(xor([], null)).toBeTrue()\n expect(xor(undefined, [])).toBeTrue()\n})\n```\n\n \n\n\n\nTypeScript test
\n\n```typescript\nimport {xor} from 'rambda'\n\ndescribe('R.xor', () => {\n it('happy', () => {\n xor(true, false) // $ExpectType boolean\n })\n it('curry', () => {\n xor(true)(false) // $ExpectType boolean\n })\n})\n```\n\n \n\n[](#xor)\n\n### zip\n\n```typescript\n\nzip(x: K[], y: V[]): KeyValuePair[]\n```\n\nIt will return a new array containing tuples of equally positions items from both `x` and `y` lists. \n\nThe returned list will be truncated to match the length of the shortest supplied list.\n\nTry this R.zip example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\nzip(x: K[], y: V[]): KeyValuePair[];\nzip(x: K[]): (y: V[]) => KeyValuePair[];\n```\n\n \n\n\n\nR.zip source
\n\n```javascript\nexport function zip(left, right){\n if (arguments.length === 1) return _right => zip(left, _right)\n\n const result = []\n const length = Math.min(left.length, right.length)\n\n for (let i = 0; i < length; i++){\n result[ i ] = [ left[ i ], right[ i ] ]\n }\n\n return result\n}\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { zip } from './zip.js'\n\nconst array1 = [ 1, 2, 3 ]\nconst array2 = [ 'A', 'B', 'C' ]\n\ntest('should return an array', () => {\n const actual = zip(array1)(array2)\n expect(actual).toBeInstanceOf(Array)\n})\n\ntest('should return and array or tuples', () => {\n const expected = [\n [ 1, 'A' ],\n [ 2, 'B' ],\n [ 3, 'C' ],\n ]\n const actual = zip(array1, array2)\n expect(actual).toEqual(expected)\n})\n\ntest('should truncate result to length of shorted input list', () => {\n const expectedA = [\n [ 1, 'A' ],\n [ 2, 'B' ],\n ]\n const actualA = zip([ 1, 2 ], array2)\n expect(actualA).toEqual(expectedA)\n\n const expectedB = [\n [ 1, 'A' ],\n [ 2, 'B' ],\n ]\n const actualB = zip(array1, [ 'A', 'B' ])\n expect(actualB).toEqual(expectedB)\n})\n```\n\n \n\n\n\nTypeScript test
\n\n```typescript\nimport {zip} from 'rambda'\n\ndescribe('R.zip', () => {\n it('happy', () => {\n const array1 = [1, 2, 3]\n const array2 = ['A', 'B', 'C']\n\n const result = zip(array1)(array2)\n result // $ExpectType KeyValuePair[]\n })\n})\n```\n\n \n\n[](#zip)\n\n### zipObj\n\n```typescript\n\nzipObj(keys: K[], values: T[]): { [P in K]: T }\n```\n\nIt will return a new object with keys of `keys` array and values of `values` array.\n\nTry this R.zipObj example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\nzipObj(keys: K[], values: T[]): { [P in K]: T };\nzipObj(keys: K[]): (values: T[]) => { [P in K]: T };\nzipObj(keys: K[], values: T[]): { [P in K]: T };\nzipObj(keys: K[]): (values: T[]) => { [P in K]: T };\n```\n\n \n\n\n\nR.zipObj source
\n\n```javascript\nimport { take } from './take.js'\n\nexport function zipObj(keys, values){\n if (arguments.length === 1) return yHolder => zipObj(keys, yHolder)\n\n return take(values.length, keys).reduce((\n prev, xInstance, i\n ) => {\n prev[ xInstance ] = values[ i ]\n\n return prev\n }, {})\n}\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { equals } from './equals.js'\nimport { zipObj } from './zipObj.js'\n\ntest('zipObj', () => {\n expect(zipObj([ 'a', 'b', 'c' ], [ 1, 2, 3 ])).toEqual({\n a : 1,\n b : 2,\n c : 3,\n })\n})\n\ntest('0', () => {\n expect(zipObj([ 'a', 'b' ])([ 1, 2, 3 ])).toEqual({\n a : 1,\n b : 2,\n })\n})\n\ntest('1', () => {\n expect(zipObj([ 'a', 'b', 'c' ])([ 1, 2 ])).toEqual({\n a : 1,\n b : 2,\n })\n})\n\ntest('ignore extra keys', () => {\n const result = zipObj([ 'a', 'b', 'c', 'd', 'e', 'f' ], [ 1, 2, 3 ])\n const expected = {\n a : 1,\n b : 2,\n c : 3,\n }\n\n expect(equals(result, expected)).toBeTrue()\n})\n```\n\n \n\n\n\nTypeScript test
\n\n```typescript\nimport {zipObj} from 'rambda'\n\ndescribe('R.zipObj', () => {\n it('happy', () => {\n // this is wrong since 24.10.2020 `@types/ramda` changes\n const result = zipObj(['a', 'b', 'c', 'd'], [1, 2, 3])\n ;[result.a, result.b, result.c, result.d] // $ExpectType number[]\n })\n it('imported from @types/ramda', () => {\n const result = zipObj(['a', 'b', 'c'], [1, 2, 3])\n const curriedResult = zipObj(['a', 'b', 'c'])([1, 2, 3])\n ;[result.a, result.b, result.c] // $ExpectType number[]\n ;[curriedResult.a, curriedResult.b, curriedResult.c] // $ExpectType number[]\n })\n})\n```\n\n \n\n[](#zipObj)\n\n### zipWith\n\n```typescript\n\nzipWith(fn: (x: T, y: U) => TResult, list1: T[], list2: U[]): TResult[]\n```\n\nTry this R.zipWith example in Rambda REPL\n\n\n\nAll TypeScript definitions
\n\n```typescript\nzipWith(fn: (x: T, y: U) => TResult, list1: T[], list2: U[]): TResult[];\nzipWith(fn: (x: T, y: U) => TResult, list1: T[]): (list2: U[]) => TResult[];\nzipWith(fn: (x: T, y: U) => TResult): (list1: T[], list2: U[]) => TResult[];\n```\n\n \n\n\n\nR.zipWith source
\n\n```javascript\nimport { curry } from './curry.js'\nimport { take } from './take.js'\n\nfunction zipWithFn(\n fn, x, y\n){\n return take(x.length > y.length ? y.length : x.length, x).map((xInstance, i) => fn(xInstance, y[ i ]))\n}\n\nexport const zipWith = curry(zipWithFn)\n```\n\n \n\n\n\nTests
\n\n```javascript\nimport { add } from './add.js'\nimport { zipWith } from './zipWith.js'\n\nconst list1 = [ 1, 2, 3 ]\nconst list2 = [ 10, 20, 30, 40 ]\nconst list3 = [ 100, 200 ]\n\ntest('when second list is shorter', () => {\n const result = zipWith(\n add, list1, list3\n )\n expect(result).toEqual([ 101, 202 ])\n})\n\ntest('when second list is longer', () => {\n const result = zipWith(\n add, list1, list2\n )\n expect(result).toEqual([ 11, 22, 33 ])\n})\n```\n\n \n\n\n\nTypeScript test
\n\n```typescript\nimport {zipWith} from 'rambda'\n\nconst list1 = [1, 2]\nconst list2 = [10, 20, 30]\n\ndescribe('R.zipWith', () => {\n it('happy', () => {\n const result = zipWith(\n (x, y) => {\n x // $ExpectType number\n y // $ExpectType number\n return `${x}-${y}`\n },\n list1,\n list2\n )\n\n result // $ExpectType string[]\n })\n it('curried', () => {\n const result = zipWith((x, y) => {\n x // $ExpectType unknown\n y // $ExpectType unknown\n return `${x}-${y}`\n })(list1, list2)\n\n result // $ExpectType string[]\n })\n})\n```\n\n \n\n[](#zipWith)\n\n## ❯ CHANGELOG\n\n9.4.2 \n\n- Fix TS issue when `R.take` is used as part of `R.pipe`.\n\nMoving away from `Ramda` types which are problematic in this case:\n\n```typescript\nconst data = ['foo', 'bar', 'baz', 'qux']\nconst result = piped(\n\tdata,\n\tfilter(\n\t\tx => x.length >= 2\n\t),\n\ttakeLast(2),\n)\n```\n\n9.4.1\n\n- Fix bug with `R.differenceWith` when two arrays has same length - [Issue #750](https://github.com/selfrefactor/rambda/issues/757)\n\n- Allow path input to not be transformed when string numbers are there - [Issue #750](https://github.com/selfrefactor/rambda/issues/750)\n\n9.4.0\n\n- Fix `deno` release\n\n- Fix too strict `true` condition in `R.ifElse` - [Issue #750](https://github.com/selfrefactor/rambda/issues/750)\n\n- Change `R.groupBy` typings to match `@types/ramda` typings\n\n9.3.0\n\n- Breaking change in relation to TS typings of `R.assoc`, `R.dissoc` and `R.modify` - https://github.com/ramda/types/pull/37\n\n- Add `R.isNotEmpty` as it is new method in `Ramda`\n\n- Fix `R.head`/`R.last` TS definition - It returns `undefined` if array has length of 0. Before \n\n9.2.1\n\n- Broken `Deno` build - [Issue #731](https://github.com/selfrefactor/rambda/issues/731)\n\n9.2.0\n\n- `R.once` TS type definition miss to context argument and its type - [Issue #728](https://github.com/selfrefactor/rambda/issues/728)\n\n- Fix implementation of `R.unless` function - https://github.com/selfrefactor/rambda/pull/726 \n\n9.1.1\n\n- Faster R.equals with Object.is short circuit - https://github.com/selfrefactor/rambda/pull/725\n\n- Fix R.cond transform is unary - https://github.com/selfrefactor/rambda/issues/720\n\n9.1.0\n\nAdd these methods\n\n- insert\n- insertAll\n- lt\n- lte\n- isNotNil\n- pickBy\n- pathSatisfies\n- swap\n- mergeDeepLeft\n\n9.0.1\n\n- Fix bad TS typings, due to missing declaration - [Issue #716](https://github.com/selfrefactor/rambda/issues/716)\n\n9.0.0\n\nBreaking change in TS definitions of `lenses` as now they are synced to `Ramda` types.\n\n- Add `R.sortWith` - [Issue #707](https://github.com/selfrefactor/rambda/issues/707)\n\n- Add `R.innerJoin`, `R.gt`, `R.gte`, `R.reduceBy`, `R.hasIn`\n\n8.6.0\n\n- Wrong typing for `R.dissocPath` - [Issue #709](https://github.com/selfrefactor/rambda/issues/709)\n\n- Update build dependencies\n\n8.5.0\n\n- Revert changes in `R.anyPass` introduced in `8.4.0` release. The reason is that the change was breaking the library older than `5.2.0` TypeScript.\n\n- Wrong `R.partial` TS definition - [Issue #705](https://github.com/selfrefactor/rambda/issues/705)\n\n- Add `R.dropRepeatsBy`\n\n- Add `R.empty`\n\n- Add `R.eqBy`\n\n- Add `R.forEachObjIndexed`\n\n8.4.0\n\n- Add `R.dissocPath`\n\n- Fix TS definitions of `R.head/R.last` and add missing handle of empty string\n\n- Add `R.removeIndex` - method was before only in `Rambdax`, but now since `R.dissocPath` is using it, it is added to main library.\n\n- Allow `R.omit` to pass numbers as part of properties to omit, i.e. `R.omit(['a', 1], {a: {1: 1, 2: 2}})`\n\n- R.keys always returns strings - [MR #700](https://github.com/selfrefactor/rambda/pull/700)\n\n- Improve `R.prepend/R.append` type interference - [MR #699](https://github.com/selfrefactor/rambda/pull/699)\n\n- Change `R.reduce` TS definitions so index is always received - [MR #696](https://github.com/selfrefactor/rambda/pull/696)\n\n- Functions as a type guard in `R.anyPass` TS definitions - [MR #695](https://github.com/selfrefactor/rambda/pull/695)\n\n- Fix R.append's curried type - [MR #694](https://github.com/selfrefactor/rambda/pull/694)\n\n- Fix cannot compare errors in `Deno` with `R.equals` - [Issue #704](https://github.com/selfrefactor/rambda/issues/704).\n\n- Fix cannot compare `BigInt` with `R.equals` \n\n8.3.0\n\nAdd the following methods:\n\n- binary\n- call\n- collectBy\n- comparator\n- composeWith\n\n8.2.0\n\nAdd the following methods:\n\n- addIndex\n- addIndexRight\n- ap\n- aperture\n- applyTo\n- ascend\n- descend\n\n8.1.0\n\n- Fix input order of TS definitions for `R.propEq` method - [Issue #688](https://github.com/selfrefactor/rambda/issues/688). The issue was due to 8.0.0 was shipped with TS definitions of `7.5.0` release.\n\n- Add `R.differenceWith` method - [Issue #91](https://github.com/selfrefactor/rambdax/issues/91)\n\n8.0.0\n\n- handle falsy values in merge methods - https://github.com/ramda/ramda/pull/3222\n\n- `R.head`/`R.last` don't return `undefined` for non-empty arrays\n\n- `R.type` supports dates in TS definition - `Rambda` already did support dates in JS.\n\n- Improve typings of `R.endsWith/startsWith` with regard to `string` input. - [PR #622](https://github.com/selfrefactor/rambda/pull/622)\n\n- Handle list as falsy value in `R.reduce` - [Ramda MR](https://github.com/ramda/ramda/pull/2997/files)\n\n- `R.nop` is removed - it will be moved to `Rambdax` as `R.noop`\n\n- `R.includes` is no longer using string literal in TypeScript definitions\n\n> Reason for breaking change - synchronize with Ramda `0.29.0` release:\n\n- change order of `R.propEq` - [Ramda MR](https://github.com/ramda/ramda/pull/2938/files)\n\n7.5.0\n\n- IMPORTANT: Remove `export` property in `package.json` in order to allow `Rambda` support for projects with `\"type\": \"module\"` in `package.json` - [Issue #667](https://github.com/selfrefactor/rambda/issues/657)\n\n- Add `R.unnest` - [Rambdax issue 89](https://github.com/selfrefactor/rambdax/issues/89)\n\n- `R.uniq` is not using `R.equals` as Ramda does - [Issue #88](https://github.com/selfrefactor/rambdax/issues/88)\n\n- Fix `R.path(['non','existing','path'], obj)` TS definition as 7.4.0 release caused TS errors - [Issue #668](https://github.com/selfrefactor/rambda/issues/668)\n\n7.4.0\n\n- Synchronize with `@types/ramda` - `R.prop`, `R.path`, `R.pickAll`\n\n- Remove `esm` Rollup output due to tree-shaking issues.\n\n- Upgrade all dev dependencies.\n\n7.3.0\n\n- Important - changing import declaration in `package.json` in order to fix tree-shaking issue - [Issue #647](https://github.com/selfrefactor/rambda/issues/647)\n\n- Add `R.modify`\n\n- Allow multiple inputs in TypeScript versions of `R.anyPass` and `R.allPass` - [Issue #642](https://github.com/selfrefactor/rambda/issues/604)\n\n- Using wrong clone of object in `R.mergeDeepRight` - [Issue #650](https://github.com/selfrefactor/rambda/issues/650)\n\n- Missing early return in `R.where` - [Issue #648](https://github.com/selfrefactor/rambda/issues/648)\n\n- `R.allPass` doesn't accept more than 1 parameters for function predicates- [Issue #604](https://github.com/selfrefactor/rambda/issues/604)\n\n7.2.1\n\n- Remove bad typings of `R.propIs` which caused the library to cannot be build with TypeScript. \n\n- Drop support for `Wallaby` as per [https://github.com/wallabyjs/public/issues/3037](https://github.com/wallabyjs/public/issues/3037)\n\n7.2.0\n\n- Wrong `R.update` if index is `-1` - [PR #593](https://github.com/selfrefactor/rambda/pull/593)\n\n- Wrong curried typings in `R.anyPass` - [Issue #642](https://github.com/selfrefactor/rambda/issues/642)\n\n- `R.modifyPath` not exported - [Issue #640](https://github.com/selfrefactor/rambda/issues/640)\n\n- Add new method `R.uniqBy`. Implementation is coming from [Ramda MR#2641](https://github.com/ramda/ramda/pull/2641)\n\n- Apply the following changes from `@types/rambda`:\n\n-- [https://github.com/DefinitelyTyped/DefinitelyTyped/commit/bab47272d52fc7bb81e85da36dbe9c905a04d067](add `AnyFunction` and `AnyConstructor`)\n\n-- Improve `R.ifElse` typings - https://github.com/DefinitelyTyped/DefinitelyTyped/pull/59291\n\n-- Make `R.propEq` safe for `null/undefined` arguments - https://github.com/ramda/ramda/pull/2594/files\n\n7.1.4\n\n- `R.mergeRight` not found on `Deno` import - [Issue #633](https://github.com/selfrefactor/rambda/issues/633)\n\n7.1.0\n\n- Add `R.mergeRight` - introduced by Ramda's latest release. While Ramda renames `R.merge`, Rambda will keep `R.merge`.\n\n- Rambda's `pipe/compose` doesn't return proper length of composed function which leads to issue with `R.applySpec`. It was fixed by using Ramda's `pipe/compose` logic - [Issue #627](https://github.com/selfrefactor/rambda/issues/627)\n\n- Replace `Async` with `Promise` as return type of `R.type`.\n\n- Add new types as TypeScript output for `R.type` - \"Map\", \"WeakMap\", \"Generator\", \"GeneratorFunction\", \"BigInt\", \"ArrayBuffer\"\n\n- Add `R.juxt` method\n\n- Add `R.propSatisfies` method\n\n- Add new methods after `Ramda` version upgrade to `0.28.0`:\n\n-- R.count\n-- R.modifyPath\n-- R.on\n-- R.whereAny\n-- R.partialObject\n\n7.0.3\n\nRambda.none has wrong logic introduced in version `7.0.0` - [Issue #625](https://github.com/selfrefactor/rambda/issues/625)\n\n7.0.2\n\nRambda doesn't work with `pnpm` due to wrong export configuration - [Issue #619](https://github.com/selfrefactor/rambda/issues/619)\n\n7.0.1\n\n- Wrong ESM export configuration in `package.json` - [Issue #614](https://github.com/selfrefactor/rambda/issues/614)\n\n7.0.0\n\n- Breaking change - sync `R.compose`/`R.pipe` with `@types/ramda`. That is significant change so as safeguard, it will lead a major bump. Important - this lead to raising required TypeScript version to `4.2.2`. In other words, to use `Rambda` you'll need TypeScript version `4.2.2` or newer.\n\nRelated commit in `@types/ramda` - https://github.com/DefinitelyTyped/DefinitelyTyped/commit/286eff4f76d41eb8f091e7437eabd8a60d97fc1f#diff-4f74803fa83a81e47cb17a7d8a4e46a7e451f4d9e5ce2f1bd7a70a72d91f4bc1\n\nThere are several other changes in `@types/ramda` as stated in [this comment](https://github.com/ramda/ramda/issues/2976#issuecomment-990408945). This leads to change of typings for the following methods in **Rambda**:\n\n-- R.unless\n\n-- R.toString\n\n-- R.ifElse\n\n-- R.always\n\n-- R.complement\n\n-- R.cond\n\n-- R.is\n\n-- R.sortBy\n\n-- R.dissoc\n\n-- R.toPairs\n\n-- R.assoc\n\n-- R.toLower\n\n-- R.toUpper\n\n- One more reason for the breaking change is changing of export declarations in `package.json` based on [this blog post](https://devblogs.microsoft.com/typescript/announcing-typescript-4-5-beta/#packagejson-exports-imports-and-self-referencing) and [this merged Ramda's PR](https://github.com/ramda/ramda/pull/2999). This also led to renaming of `babel.config.js` to `babel.config.cjs`. \n\n- Add `R.apply`, `R.bind` and `R.unapply`\n\n- `R.startsWith/R.endsWith` now support lists as inputs. This way, it matches current Ramda behavior. \n\n- Remove unused typing for `R.chain`.\n\n- `R.map`/`R.filter` no longer accept bad inputs as iterable. This way, Rambda behaves more like Ramda, which also throws.\n\n- Make `R.lastIndexOf` follow the logic of `R.indexOf`.\n\n- Change `R.type` logic to Ramda logic. This way, `R.type` can return `Error` and `Set` as results.\n\n- Add missing logic in `R.equals` to compare sets - [Issue #599](https://github.com/selfrefactor/rambda/issues/599)\n\n- Improve list cloning - [Issue #595](https://github.com/selfrefactor/rambda/issues/595)\n\n- Handle multiple inputs with `R.allPass` and `R.anyPass` - [Issue #604](https://github.com/selfrefactor/rambda/issues/604)\n\n- Fix `R.length` wrong logic with inputs as `{length: 123}` - [Issue #606](https://github.com/selfrefactor/rambda/issues/606).\n\n- Improve non-curry typings of `R.merge` by using types from [mobily/ts-belt](https://github.com/mobily/ts-belt).\n\n- Improve performance of `R.uniqWith`.\n\n- Wrong `R.update` if index is `-1` - [PR #593](https://github.com/selfrefactor/rambda/pull/593)\n\n- Make `R.eqProps` safe for falsy inputs - based on [this opened Ramda PR](https://github.com/ramda/ramda/pull/2943).\n\n- Incorrect benchmarks for `R.pipe/R.compose` - [Issue #608](https://github.com/selfrefactor/rambda/issues/608)\n\n- Fix `R.last/R.head` typings - [Issue #609](https://github.com/selfrefactor/rambda/issues/609) \n\n6.9.0\n\n- Fix slow `R.uniq` methods - [Issue #581](https://github.com/selfrefactor/rambda/issues/581)\n\nFixing `R.uniq` was done by improving `R.indexOf` which has performance implication to all methods importing `R.indexOf`:\n\n- R.includes\n- R.intersection\n- R.difference\n- R.excludes\n- R.symmetricDifference\n- R.union\n\n- R.without no longer support the following case - `without('0:1', ['0', '0:1']) // => ['0']`. Now it throws as the first argument should be a list, not a string. Ramda, on the other hand, returns an empty list - https://github.com/ramda/ramda/issues/3086. \n\n6.8.3\n\n- Fix TypeScript build process with `rambda/immutable` - [Issue #572](https://github.com/selfrefactor/rambda/issues/572)\n\n- Add `R.objOf` method\n\n- Add `R.mapObjIndexed` method\n\n- Publish shorter README.md version to NPM\n\n6.8.0\n\n- `R.has` use `Object.prototype.hasOwnProperty`- [Issue #572](https://github.com/selfrefactor/rambda/issues/572)\n\n- Expose `immutable.ts` typings which are Rambda typings with `readonly` statements - [Issue #565](https://github.com/selfrefactor/rambda/issues/565)\n\n- Fix `R.intersection` wrong order compared to Ramda.\n\n- `R.path` wrong return of `null` instead of `undefined` when path value is `null` - [PR #577](https://github.com/selfrefactor/rambda/pull/577)\n\n6.7.0\n\n- Remove `ts-toolbelt` types from TypeScript definitions. Most affected are the following methods, which lose one of its curried definitions:\n\n1. R.maxBy\n2. R.minBy\n3. R.pathEq\n4. R.viewOr\n5. R.when\n6. R.merge\n7. R.mergeDeepRight\n8. R.mergeLeft\n\n6.6.0\n\n- Change `R.piped` typings to mimic that of `R.pipe`. Main difference is that `R.pipe` is focused on unary functions.\n\n- Fix wrong logic when `R.without` use `R.includes` while it should use array version of `R.includes`.\n\n- Use uglify plugin for UMD bundle.\n\n- Remove `dist` folder from `.gitignore` in order to fix `Deno` broken package. [Issue #570](https://github.com/selfrefactor/rambda/issues/570)\n\n- Improve `R.fromPairs` typings - [Issue #567](https://github.com/selfrefactor/rambda/issues/567)\n\n6.5.3\n\n- Wrong logic where `R.without` use `R.includes` while it should use the array version of `R.includes`\n\nThis is Ramda bug, that Rambda also has before this release - https://github.com/ramda/ramda/issues/3086\n\n6.5.2\n\n- Wrong `R.defaultTo` typings - changes introduced in v6.5.0 are missing their TS equivalent.\n\n- Update dependencies\n\n6.5.1\n\nFix wrong versions in changelog\n\n6.5.0\n\n- `R.defaultTo` no longer accepts infinite inputs, thus it follows Ramda implementation.\n\n- `R.equals` supports equality of functions.\n\n- `R.pipe` doesn't use `R.compose`.\n\n- Close [Issue #561](https://github.com/selfrefactor/rambda/issues/561) - export several internal TS interfaces and types\n\n- Close [Issue #559](https://github.com/selfrefactor/rambda/issues/559) - improve `R.propOr` typings\n\n- Add `CHANGELOG.md` file in release files list\n\n> This is only part of the changelog. You can read the full text in [CHANGELOG.md](CHANGELOG.md) file.\n\n[](#-changelog)\n\n## ❯ Additional info\n\n> Most influential contributors(in alphabetical order)\n\n-  [@farwayer](https://github.com/farwayer) - improving performance in R.find, R.filter; give the idea how to make benchmarks more reliable;\n\n-  [@thejohnfreeman](https://github.com/thejohnfreeman) - add R.assoc, R.chain;\n\n-  [@peeja](https://github.com/peeja) - add several methods and fix mutiple issues; provides great MR documentation\n\n-  [@helmuthdu](https://github.com/helmuthdu) - add R.clone; help improve code style;\n\n-  [@jpgorman](https://github.com/jpgorman) - add R.zip, R.reject, R.without, R.addIndex;\n\n-  [@ku8ar](https://github.com/ku8ar) - add R.slice, R.propOr, R.identical, R.propIs and several math related methods; introduce the idea to display missing Ramda methods;\n\n-  [@romgrk](https://github.com/romgrk) - add R.groupBy, R.indexBy, R.findLast, R.findLastIndex;\n\n-  [@squidfunk](https://github.com/squidfunk) - add R.assocPath, R.symmetricDifference, R.difference, R.intersperse;\n\n-  [@synthet1c](https://github.com/synthet1c) - add all lenses methods; add R.applySpec, R.converge;\n\n-  [@vlad-zhukov](https://github.com/vlad-zhukov) - help with configuring Rollup, Babel; change export file to use ES module exports;\n\n> Rambda references\n\n- [Interview with Dejan Totef at SurviveJS blog](https://survivejs.com/blog/rambda-interview/)\n\n- [Awesome functional Javascript programming libraries](https://github.com/stoeffel/awesome-fp-js#libraries)\n\n- [Overview of Rambda pros/cons](https://mobily.github.io/ts-belt/docs/#rambda-%EF%B8%8F)\n\n> Links to Rambda\n\n- [awesome-fp-js](https://github.com/stoeffel/awesome-fp-js)\n\n- [Web Tools Weekly #280](https://mailchi.mp/webtoolsweekly/web-tools-280)\n\n- [awesome-docsify](https://github.com/docsifyjs/awesome-docsify)\n\n> Deprecated from `Used by` section\n\n- [SAP's Cloud SDK](https://github.com/SAP/cloud-sdk) - This repo doesn't uses `Rambda` since *October/2020* [commit that removes Rambda](https://github.com/SAP/cloud-sdk/commit/b29b4f915c4e4e9c2441e7b6b67cf83dac1fdac3)\n\n[](#-additional-info)\n\n## My other libraries\n\n\n\n## Stargazers over time\n\n[](https://starchart.cc/selfrefactor/rambda)",
"licenseText": "MIT License\n\nCopyright (c) 2017 Dejan Toteff\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
},
"artifacts": [],
"remote": {
"resolved": "https://registry.npmjs.org/rambda/-/rambda-9.4.2.tgz",
"type": "tarball",
"reference": "https://registry.npmjs.org/rambda/-/rambda-9.4.2.tgz",
"hash": "",
"integrity": "sha512-++euMfxnl7OgaEKwXh9QqThOjMeta2HH001N1v4mYQzBjJBnmXBh2BCK6dZAbICFVXOFUVD3xFG0R3ZPU0mxXw==",
"registry": "npm",
"packageName": "rambda",
"cacheIntegrity": "sha512-++euMfxnl7OgaEKwXh9QqThOjMeta2HH001N1v4mYQzBjJBnmXBh2BCK6dZAbICFVXOFUVD3xFG0R3ZPU0mxXw== sha1-Gg2mFxylgw6IMR8Ag+X9i5RaMq0="
},
"registry": "npm",
"hash": "fbe7ae31fc6797b3a06842b05e1f50a9384e8cc7ad6b61c7d34d4dd6fe26610cc18c9067997061d8108ae9d6406c80855573855150f7c451b447764f5349b15f"
}