> | undefined): T
```
It returns either `defaultValue` or the value of `property` in `obj`.
Try this R.propOr example in Rambda REPL
All TypeScript definitions
```typescript
propOr(defaultValue: T, property: P, obj: Partial> | undefined): T;
propOr(defaultValue: T, property: P): (obj: Partial> | undefined) => T;
propOr(defaultValue: T): {
(property: P, obj: Partial> | undefined): T;
(property: P): (obj: Partial> | undefined) => T;
}
```
R.propOr source
```javascript
import { curry } from './curry.js'
import { defaultTo } from './defaultTo.js'
function propOrFn(
defaultValue, property, obj
){
if (!obj) return defaultValue
return defaultTo(defaultValue, obj[ property ])
}
export const propOr = curry(propOrFn)
```
Tests
```javascript
import { propOr } from './propOr.js'
test('propOr (result)', () => {
const obj = { a : 1 }
expect(propOr(
'default', 'a', obj
)).toBe(1)
expect(propOr(
'default', 'notExist', obj
)).toBe('default')
expect(propOr(
'default', 'notExist', null
)).toBe('default')
})
test('propOr (currying)', () => {
const obj = { a : 1 }
expect(propOr('default')('a', obj)).toBe(1)
expect(propOr('default', 'a')(obj)).toBe(1)
expect(propOr('default')('notExist', obj)).toBe('default')
expect(propOr('default', 'notExist')(obj)).toBe('default')
})
```
TypeScript test
```typescript
import {propOr} from 'rambda'
const obj = {foo: 'bar'}
const property = 'foo'
const fallback = 'fallback'
describe('R.propOr', () => {
it('happy', () => {
const result = propOr(fallback, property, obj)
result // $ExpectType string
})
it('curry 1', () => {
const result = propOr(fallback)(property, obj)
result // $ExpectType string
})
it('curry 2', () => {
const result = propOr(fallback, property)(obj)
result // $ExpectType string
})
it('curry 3', () => {
const result = propOr(fallback)(property)(obj)
result // $ExpectType string
})
})
```
[](#propOr)
### props
```typescript
props(propsToPick: P[], obj: Record
): T[]
```
It takes list with properties `propsToPick` and returns a list with property values in `obj`.
Try this R.props example in Rambda REPL
All TypeScript definitions
```typescript
props(propsToPick: P[], obj: Record
): T[];
props
(propsToPick: P[]): (obj: Record) => T[];
props
(propsToPick: P[]): (obj: Record
) => T[];
```
R.props source
```javascript
import { isArray } from './_internals/isArray.js'
import { mapArray } from './map.js'
export function props(propsToPick, obj){
if (arguments.length === 1){
return _obj => props(propsToPick, _obj)
}
if (!isArray(propsToPick)){
throw new Error('propsToPick is not a list')
}
return mapArray(prop => obj[ prop ], propsToPick)
}
```
Tests
```javascript
import { props } from './props.js'
const obj = {
a : 1,
b : 2,
}
const propsToPick = [ 'a', 'c' ]
test('happy', () => {
const result = props(propsToPick, obj)
expect(result).toEqual([ 1, undefined ])
})
test('curried', () => {
const result = props(propsToPick)(obj)
expect(result).toEqual([ 1, undefined ])
})
test('wrong input', () => {
expect(() => props(null)(obj)).toThrowErrorMatchingInlineSnapshot('"propsToPick is not a list"')
})
```
TypeScript test
```typescript
import {props} from 'rambda'
const obj = {a: 1, b: 2}
describe('R.props', () => {
it('happy', () => {
const result = props(['a', 'b'], obj)
result // $ExpectType number[]
})
it('curried', () => {
const result = props(['a', 'b'])(obj)
result // $ExpectType number[]
})
})
```
[](#props)
### propSatisfies
```typescript
propSatisfies(predicate: Predicate, property: string, obj: Record): boolean
```
It returns `true` if the object property satisfies a given predicate.
Try this R.propSatisfies example in Rambda REPL
All TypeScript definitions
```typescript
propSatisfies(predicate: Predicate, property: string, obj: Record): boolean;
propSatisfies(predicate: Predicate, property: string): (obj: Record) => boolean;
```
R.propSatisfies source
```javascript
import { curry } from './curry.js'
import { prop } from './prop.js'
function propSatisfiesFn(
predicate, property, obj
){
return predicate(prop(property, obj))
}
export const propSatisfies = curry(propSatisfiesFn)
```
Tests
```javascript
import { propSatisfies } from './propSatisfies.js'
const obj = { a : 1 }
test('when true', () => {
expect(propSatisfies(
x => x > 0, 'a', obj
)).toBeTrue()
})
test('when false', () => {
expect(propSatisfies(x => x < 0, 'a')(obj)).toBeFalse()
})
```
TypeScript test
```typescript
import {propSatisfies} from 'rambda'
const obj = {a: 1}
describe('R.propSatisfies', () => {
it('happy', () => {
const result = propSatisfies(x => x > 0, 'a', obj)
result // $ExpectType boolean
})
it('curried requires explicit type', () => {
const result = propSatisfies(x => x > 0, 'a')(obj)
result // $ExpectType boolean
})
})
```
[](#propSatisfies)
### range
```typescript
range(startInclusive: number, endExclusive: number): number[]
```
It returns list of numbers between `startInclusive` to `endExclusive` markers.
Try this R.range example in Rambda REPL
All TypeScript definitions
```typescript
range(startInclusive: number, endExclusive: number): number[];
range(startInclusive: number): (endExclusive: number) => number[];
```
R.range source
```javascript
export function range(start, end){
if (arguments.length === 1) return _end => range(start, _end)
if (Number.isNaN(Number(start)) || Number.isNaN(Number(end))){
throw new TypeError('Both arguments to range must be numbers')
}
if (end < start) return []
const len = end - start
const willReturn = Array(len)
for (let i = 0; i < len; i++){
willReturn[ i ] = start + i
}
return willReturn
}
```
Tests
```javascript
import { range } from './range.js'
test('happy', () => {
expect(range(0, 10)).toEqual([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ])
})
test('end range is bigger than start range', () => {
expect(range(7, 3)).toEqual([])
expect(range(5, 5)).toEqual([])
})
test('with bad input', () => {
const throwMessage = 'Both arguments to range must be numbers'
expect(() => range('a', 6)).toThrowWithMessage(Error, throwMessage)
expect(() => range(6, 'z')).toThrowWithMessage(Error, throwMessage)
})
test('curry', () => {
expect(range(0)(10)).toEqual([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ])
})
```
TypeScript test
```typescript
import {range} from 'rambda'
describe('R.range', () => {
it('happy', () => {
const result = range(1, 4)
result // $ExpectType number[]
})
it('curried', () => {
const result = range(1)(4)
result // $ExpectType number[]
})
})
```
[](#range)
### reduce
Try this R.reduce example in Rambda REPL
[](#reduce)
### reduceBy
Try this R.reduceBy example in Rambda REPL
[](#reduceBy)
### reject
```typescript
reject(predicate: Predicate, list: T[]): T[]
```
It has the opposite effect of `R.filter`.
Try this R.reject example in Rambda REPL
All TypeScript definitions
```typescript
reject(predicate: Predicate, list: T[]): T[];
reject(predicate: Predicate): (list: T[]) => T[];
reject(predicate: Predicate, obj: Dictionary): Dictionary;
reject(predicate: Predicate): (obj: Dictionary) => Dictionary;
```
R.reject source
```javascript
import { filter } from './filter.js'
export function reject(predicate, list){
if (arguments.length === 1) return _list => reject(predicate, _list)
return filter(x => !predicate(x), list)
}
```
Tests
```javascript
import { reject } from './reject.js'
const isOdd = n => n % 2 === 1
test('with array', () => {
expect(reject(isOdd)([ 1, 2, 3, 4 ])).toEqual([ 2, 4 ])
})
test('with object', () => {
const obj = {
a : 1,
b : 2,
c : 3,
d : 4,
}
expect(reject(isOdd, obj)).toEqual({
b : 2,
d : 4,
})
})
```
TypeScript test
```typescript
import {reject} from 'rambda'
describe('R.reject with array', () => {
it('happy', () => {
const result = reject(
x => {
x // $ExpectType number
return x > 1
},
[1, 2, 3]
)
result // $ExpectType number[]
})
it('curried require explicit type', () => {
const result = reject(x => {
x // $ExpectType number
return x > 1
})([1, 2, 3])
result // $ExpectType number[]
})
})
describe('R.reject with objects', () => {
it('happy', () => {
const result = reject(
x => {
x // $ExpectType number
return x > 1
},
{a: 1, b: 2}
)
result // $ExpectType Dictionary
})
it('curried require dummy type', () => {
const result = reject(x => {
return x > 1
})({a: 1, b: 2})
result // $ExpectType Dictionary
})
})
```
[](#reject)
### removeIndex
```typescript
removeIndex(index: number, list: T[]): T[]
```
It returns a copy of `list` input with removed `index`.
Try this R.removeIndex example in Rambda REPL
All TypeScript definitions
```typescript
removeIndex(index: number, list: T[]): T[];
removeIndex(index: number): (list: T[]) => T[];
```
R.removeIndex source
```javascript
export function removeIndex(index, list){
if (arguments.length === 1) return _list => removeIndex(index, _list)
if (index <= 0) return list.slice(1)
if (index >= list.length - 1) return list.slice(0, list.length - 1)
return [ ...list.slice(0, index), ...list.slice(index + 1) ]
}
```
Tests
```javascript
import { removeIndex } from './removeIndex.js'
const list = [ 1, 2, 3, 4 ]
test('first or before first index', () => {
expect(removeIndex(-2, list)).toEqual([ 2, 3, 4 ])
expect(removeIndex(-2)(list)).toEqual([ 2, 3, 4 ])
})
test('last or after last index', () => {
expect(removeIndex(4, list)).toEqual([ 1, 2, 3 ])
expect(removeIndex(10, list)).toEqual([ 1, 2, 3 ])
})
test('middle index', () => {
expect(removeIndex(1, list)).toEqual([ 1, 3, 4 ])
expect(removeIndex(2, list)).toEqual([ 1, 2, 4 ])
})
```
TypeScript test
```typescript
import {removeIndex} from 'rambda'
describe('R.removeIndex', () => {
it('happy', () => {
const result = removeIndex(1, [1, 2, 3])
result // $ExpectType number[]
})
it('curried', () => {
const result = removeIndex(1)([1, 2, 3])
result // $ExpectType number[]
})
})
```
[](#removeIndex)
### repeat
```typescript
repeat(x: T): (timesToRepeat: number) => T[]
```
Try this R.repeat example in Rambda REPL
All TypeScript definitions
```typescript
repeat(x: T): (timesToRepeat: number) => T[];
repeat(x: T, timesToRepeat: number): T[];
```
R.repeat source
```javascript
export function repeat(x, timesToRepeat){
if (arguments.length === 1){
return _timesToRepeat => repeat(x, _timesToRepeat)
}
return Array(timesToRepeat).fill(x)
}
```
Tests
```javascript
import { repeat } from './repeat.js'
test('repeat', () => {
expect(repeat('')(3)).toEqual([ '', '', '' ])
expect(repeat('foo', 3)).toEqual([ 'foo', 'foo', 'foo' ])
const obj = {}
const arr = repeat(obj, 3)
expect(arr).toEqual([ {}, {}, {} ])
expect(arr[ 0 ] === arr[ 1 ]).toBeTrue()
})
```
TypeScript test
```typescript
import {repeat} from 'rambda'
describe('R.repeat', () => {
it('happy', () => {
const result = repeat(4, 7)
result // $ExpectType number[]
})
it('curried', () => {
const result = repeat(4)(7)
result // $ExpectType number[]
})
})
```
[](#repeat)
### replace
```typescript
replace(strOrRegex: RegExp | string, replacer: RegExpReplacer, str: string): string
```
It replaces `strOrRegex` found in `str` with `replacer`.
Try this R.replace example in Rambda REPL
All TypeScript definitions
```typescript
replace(strOrRegex: RegExp | string, replacer: RegExpReplacer, str: string): string;
replace(strOrRegex: RegExp | string, replacer: RegExpReplacer): (str: string) => string;
replace(strOrRegex: RegExp | string): (replacer: RegExpReplacer) => (str: string) => string;
```
R.replace source
```javascript
import { curry } from './curry.js'
function replaceFn(
pattern, replacer, str
){
return str.replace(pattern, replacer)
}
export const replace = curry(replaceFn)
```
Tests
```javascript
import { replace } from './replace.js'
test('happy', () => {
expect(replace(
/\s/g, '|', 'foo bar baz'
)).toBe('foo|bar|baz')
})
test('with function as replacer input', () => {
expect(replace(
/\s/g,
(
match, offset, str
) => {
expect(match).toBe(' ')
expect([ 3, 7 ].includes(offset)).toBeTrue()
expect(str).toBe('foo bar baz')
return '|'
},
'foo bar baz'
)).toBe('foo|bar|baz')
})
```
TypeScript test
```typescript
import {replace} from 'rambda'
const str = 'foo bar foo'
const replacer = 'bar'
describe('R.replace', () => {
it('happy', () => {
const result = replace(/foo/g, replacer, str)
result // $ExpectType string
})
it('with string as search pattern', () => {
const result = replace('foo', replacer, str)
result // $ExpectType string
})
it('with function as replacer', () => {
const result = replace('f(o)o', (m: string, p1: string, offset: number) => {
m // $ExpectType string
p1 // $ExpectType string
offset // $ExpectType number
return p1
}, str)
result // $ExpectType string
})
})
describe('R.replace - curried', () => {
it('happy', () => {
const result = replace(/foo/g, replacer)(str)
result // $ExpectType string
})
it('with string as search pattern', () => {
const result = replace('foo', replacer)(str)
result // $ExpectType string
})
it('with function as replacer', () => {
const result = replace('f(o)o')((m: string, p1: string, offset: number) => {
m // $ExpectType string
p1 // $ExpectType string
offset // $ExpectType number
return p1
})(str)
result // $ExpectType string
})
})
```
[](#replace)
### reverse
```typescript
reverse(input: T[]): T[]
```
It returns a reversed copy of list or string `input`.
Try this R.reverse example in Rambda REPL
All TypeScript definitions
```typescript
reverse(input: T[]): T[];
reverse(input: string): string;
```
R.reverse source
```javascript
export function reverse(listOrString) {
if (typeof listOrString === 'string') {
return listOrString.split('').reverse().join('')
}
const clone = listOrString.slice()
return clone.reverse()
}
```
Tests
```javascript
import {reverse} from './reverse.js'
test('happy', () => {
expect(reverse([1, 2, 3])).toEqual([3, 2, 1])
})
test('with string', () => {
expect(reverse('baz')).toBe('zab')
})
test("it doesn't mutate", () => {
const arr = [1, 2, 3]
expect(reverse(arr)).toEqual([3, 2, 1])
expect(arr).toEqual([1, 2, 3])
})
```
TypeScript test
```typescript
import {reverse} from 'rambda'
const list = [1, 2, 3, 4, 5]
describe('R.reverse', () => {
it('happy', () => {
const result = reverse(list)
result // $ExpectType number[]
})
})
```
[](#reverse)
### set
```typescript
set(lens: Lens): {
(a: A): (obj: S) => S
(a: A, obj: S): S
}
```
It returns a copied **Object** or **Array** with modified `lens` focus set to `replacer` value.
Try this R.set example in Rambda REPL
All TypeScript definitions
```typescript
set(lens: Lens): {
(a: A): (obj: S) => S
(a: A, obj: S): S
};
set(lens: Lens, a: A): (obj: S) => S;
set(lens: Lens, a: A, obj: S): S;
```
R.set source
```javascript
import {always} from './always.js'
import {curry} from './curry.js'
import {over} from './over.js'
function setFn(lens, replacer, x) {
return over(lens, always(replacer), x)
}
export const set = curry(setFn)
```
Tests
```javascript
import {assoc} from './assoc.js'
import {lens} from './lens.js'
import {lensIndex} from './lensIndex.js'
import {lensPath} from './lensPath.js'
import {prop} from './prop.js'
import {set} from './set.js'
const testObject = {
foo: 'bar',
baz: {
a: 'x',
b: 'y',
},
}
test('assoc lens', () => {
const assocLens = lens(prop('foo'), assoc('foo'))
const result = set(assocLens, 'FOO', testObject)
const expected = {
...testObject,
foo: 'FOO',
}
expect(result).toEqual(expected)
})
test('path lens', () => {
const pathLens = lensPath('baz.a')
const result = set(pathLens, 'z', testObject)
const expected = {
...testObject,
baz: {
a: 'z',
b: 'y',
},
}
expect(result).toEqual(expected)
})
test('index lens', () => {
const indexLens = lensIndex(0)
const result = set(indexLens, 3, [1, 2])
expect(result).toEqual([3, 2])
})
```
[](#set)
### slice
```typescript
slice(from: number, to: number, input: string): string
```
Try this R.slice example in Rambda REPL
All TypeScript definitions
```typescript
slice(from: number, to: number, input: string): string;
slice(from: number, to: number, input: T[]): T[];
slice(from: number, to: number): {
(input: string): string;
(input: T[]): T[];
};
slice(from: number): {
(to: number, input: string): string;
(to: number, input: T[]): T[];
};
```
R.slice source
```javascript
import { curry } from './curry.js'
function sliceFn(
from, to, list
){
return list.slice(from, to)
}
export const slice = curry(sliceFn)
```
Tests
```javascript
import { slice } from './slice.js'
test('slice', () => {
expect(slice(
1, 3, [ 'a', 'b', 'c', 'd' ]
)).toEqual([ 'b', 'c' ])
expect(slice(
1, Infinity, [ 'a', 'b', 'c', 'd' ]
)).toEqual([ 'b', 'c', 'd' ])
expect(slice(
0, -1, [ 'a', 'b', 'c', 'd' ]
)).toEqual([ 'a', 'b', 'c' ])
expect(slice(
-3, -1, [ 'a', 'b', 'c', 'd' ]
)).toEqual([ 'b', 'c' ])
expect(slice(
0, 3, 'ramda'
)).toBe('ram')
})
```
TypeScript test
```typescript
import {slice} from 'rambda'
const list = [1, 2, 3, 4, 5]
describe('R.slice', () => {
it('happy', () => {
const result = slice(1, 3, list)
result // $ExpectType number[]
})
it('curried', () => {
const result = slice(1, 3)(list)
result // $ExpectType number[]
})
})
```
[](#slice)
### sort
```typescript
sort(sortFn: (a: T, b: T) => number, list: T[]): T[]
```
It returns copy of `list` sorted by `sortFn` function, where `sortFn` needs to return only `-1`, `0` or `1`.
Try this R.sort example in Rambda REPL
All TypeScript definitions
```typescript
sort(sortFn: (a: T, b: T) => number, list: T[]): T[];
sort(sortFn: (a: T, b: T) => number): (list: T[]) => T[];
```
R.sort source
```javascript
import { cloneList } from './_internals/cloneList.js'
export function sort(sortFn, list){
if (arguments.length === 1) return _list => sort(sortFn, _list)
return cloneList(list).sort(sortFn)
}
```
Tests
```javascript
import { sort } from './sort.js'
const fn = (a, b) => a > b ? 1 : -1
test('sort', () => {
expect(sort((a, b) => a - b)([ 2, 3, 1 ])).toEqual([ 1, 2, 3 ])
})
test('it doesn\'t mutate', () => {
const list = [ 'foo', 'bar', 'baz' ]
expect(sort(fn, list)).toEqual([ 'bar', 'baz', 'foo' ])
expect(list[ 0 ]).toBe('foo')
expect(list[ 1 ]).toBe('bar')
expect(list[ 2 ]).toBe('baz')
})
```
TypeScript test
```typescript
import {sort} from 'rambda'
const list = [3, 0, 5, 2, 1]
function sortFn(a: number, b: number): number {
return a > b ? 1 : -1
}
describe('R.sort', () => {
it('happy', () => {
const result = sort(sortFn, list)
result // $ExpectType number[]
})
it('curried', () => {
const result = sort(sortFn)(list)
result // $ExpectType number[]
})
})
```
[](#sort)
### sortBy
```typescript
sortBy(sortFn: (a: T) => Ord, list: T[]): T[]
```
It 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`.
Try this R.sortBy example in Rambda REPL
All TypeScript definitions
```typescript
sortBy(sortFn: (a: T) => Ord, list: T[]): T[];
sortBy(sortFn: (a: T) => Ord): (list: T[]) => T[];
sortBy(sortFn: (a: any) => Ord): (list: T[]) => T[];
```
R.sortBy source
```javascript
import { cloneList } from './_internals/cloneList.js'
export function sortBy(sortFn, list){
if (arguments.length === 1) return _list => sortBy(sortFn, _list)
const clone = cloneList(list)
return clone.sort((a, b) => {
const aSortResult = sortFn(a)
const bSortResult = sortFn(b)
if (aSortResult === bSortResult) return 0
return aSortResult < bSortResult ? -1 : 1
})
}
```
Tests
```javascript
import { compose } from './compose.js'
import { prop } from './prop.js'
import { sortBy } from './sortBy.js'
import { toLower } from './toLower.js'
test('happy', () => {
const input = [ { a : 2 }, { a : 1 }, { a : 1 }, { a : 3 } ]
const expected = [ { a : 1 }, { a : 1 }, { a : 2 }, { a : 3 } ]
const result = sortBy(x => x.a)(input)
expect(result).toEqual(expected)
})
test('with compose', () => {
const alice = {
name : 'ALICE',
age : 101,
}
const bob = {
name : 'Bob',
age : -10,
}
const clara = {
name : 'clara',
age : 314.159,
}
const people = [ clara, bob, alice ]
const sortByNameCaseInsensitive = sortBy(compose(toLower, prop('name')))
expect(sortByNameCaseInsensitive(people)).toEqual([ alice, bob, clara ])
})
```
TypeScript test
```typescript
import {sortBy, pipe} from 'rambda'
interface Input {
a: number,
}
describe('R.sortBy', () => {
it('passing type to sort function', () => {
function fn(x: any): number {
return x.a
}
function fn2(x: Input): number {
return x.a
}
const input = [{a: 2}, {a: 1}, {a: 0}]
const result = sortBy(fn, input)
const curriedResult = sortBy(fn2)(input)
result // $ExpectType { a: number; }[]
curriedResult // $ExpectType Input[]
result[0].a // $ExpectType number
curriedResult[0].a // $ExpectType number
})
it('passing type to sort function and list', () => {
function fn(x: Input): number {
return x.a
}
const input: Input[] = [{a: 2}, {a: 1}, {a: 0}]
const result = sortBy(fn, input)
const curriedResult = sortBy(fn)(input)
result // $ExpectType Input[]
curriedResult // $ExpectType Input[]
result[0].a // $ExpectType number
})
it('with R.pipe', () => {
interface Obj {
value: number,
}
const fn = pipe(sortBy(x => x.value))
const result = fn([{value: 1}, {value: 2}])
result // $ExpectType Obj[]
})
})
```
[](#sortBy)
### sortWith
Try this R.sortWith example in Rambda REPL
[](#sortWith)
### split
```typescript
split(separator: string | RegExp): (str: string) => string[]
```
Curried version of `String.prototype.split`
Try this R.split example in Rambda REPL
All TypeScript definitions
```typescript
split(separator: string | RegExp): (str: string) => string[];
split(separator: string | RegExp, str: string): string[];
```
R.split source
```javascript
export function split(separator, str){
if (arguments.length === 1) return _str => split(separator, _str)
return str.split(separator)
}
```
Tests
```javascript
import { split } from './split.js'
const str = 'foo|bar|baz'
const splitChar = '|'
const expected = [ 'foo', 'bar', 'baz' ]
test('happy', () => {
expect(split(splitChar, str)).toEqual(expected)
})
test('curried', () => {
expect(split(splitChar)(str)).toEqual(expected)
})
```
TypeScript test
```typescript
import {split} from 'rambda'
const str = 'foo|bar|baz'
const splitChar = '|'
describe('R.split', () => {
it('happy', () => {
const result = split(splitChar, str)
result // $ExpectType string[]
})
it('curried', () => {
const result = split(splitChar)(str)
result // $ExpectType string[]
})
})
```
[](#split)
### splitAt
```typescript
splitAt(index: number, input: T[]): [T[], T[]]
```
It splits string or array at a given index.
Try this R.splitAt example in Rambda REPL
All TypeScript definitions
```typescript
splitAt(index: number, input: T[]): [T[], T[]];
splitAt(index: number, input: string): [string, string];
splitAt(index: number): {
(input: T[]): [T[], T[]];
(input: string): [string, string];
};
```
R.splitAt source
```javascript
import { isArray } from './_internals/isArray.js'
import { drop } from './drop.js'
import { maybe } from './maybe.js'
import { take } from './take.js'
export function splitAt(index, input){
if (arguments.length === 1){
return _list => splitAt(index, _list)
}
if (!input) throw new TypeError(`Cannot read property 'slice' of ${ input }`)
if (!isArray(input) && typeof input !== 'string') return [ [], [] ]
const correctIndex = maybe(
index < 0,
input.length + index < 0 ? 0 : input.length + index,
index
)
return [ take(correctIndex, input), drop(correctIndex, input) ]
}
```
Tests
```javascript
import { splitAt as splitAtRamda } from 'ramda'
import { splitAt } from './splitAt.js'
const list = [ 1, 2, 3 ]
const str = 'foo bar'
test('with array', () => {
const result = splitAt(2, list)
expect(result).toEqual([ [ 1, 2 ], [ 3 ] ])
})
test('with array - index is negative number', () => {
const result = splitAt(-6, list)
expect(result).toEqual([ [], list ])
})
test('with array - index is out of scope', () => {
const result = splitAt(4, list)
expect(result).toEqual([ [ 1, 2, 3 ], [] ])
})
test('with string', () => {
const result = splitAt(4, str)
expect(result).toEqual([ 'foo ', 'bar' ])
})
test('with string - index is negative number', () => {
const result = splitAt(-2, str)
expect(result).toEqual([ 'foo b', 'ar' ])
})
test('with string - index is out of scope', () => {
const result = splitAt(10, str)
expect(result).toEqual([ str, '' ])
})
test('with array - index is out of scope', () => {
const result = splitAt(4)(list)
expect(result).toEqual([ [ 1, 2, 3 ], [] ])
})
const badInputs = [ 1, true, /foo/g, {} ]
const throwingBadInputs = [ null, undefined ]
test('with bad inputs', () => {
throwingBadInputs.forEach(badInput => {
expect(() => splitAt(1, badInput)).toThrowWithMessage(TypeError,
`Cannot read property 'slice' of ${ badInput }`)
expect(() => splitAtRamda(1, badInput)).toThrowWithMessage(TypeError,
`Cannot read properties of ${ badInput } (reading 'slice')`)
})
badInputs.forEach(badInput => {
const result = splitAt(1, badInput)
const ramdaResult = splitAtRamda(1, badInput)
expect(result).toEqual(ramdaResult)
})
})
```
TypeScript test
```typescript
import {splitAt} from 'rambda'
const index = 1
const str = 'foo'
const list = [1, 2, 3]
describe('R.splitAt with array', () => {
it('happy', () => {
const result = splitAt(index, list)
result // $ExpectType [number[], number[]]
})
it('curried', () => {
const result = splitAt(index)(list)
result // $ExpectType [number[], number[]]
})
})
describe('R.splitAt with string', () => {
it('happy', () => {
const result = splitAt(index, str)
result // $ExpectType [string, string]
})
it('curried', () => {
const result = splitAt(index)(str)
result // $ExpectType [string, string]
})
})
```
[](#splitAt)
### splitEvery
```typescript
splitEvery(sliceLength: number, input: T[]): (T[])[]
```
It splits `input` into slices of `sliceLength`.
Try this R.splitEvery example in Rambda REPL
All TypeScript definitions
```typescript
splitEvery(sliceLength: number, input: T[]): (T[])[];
splitEvery(sliceLength: number, input: string): string[];
splitEvery(sliceLength: number): {
(input: string): string[];
(input: T[]): (T[])[];
};
```
R.splitEvery source
```javascript
export function splitEvery(sliceLength, listOrString){
if (arguments.length === 1){
return _listOrString => splitEvery(sliceLength, _listOrString)
}
if (sliceLength < 1){
throw new Error('First argument to splitEvery must be a positive integer')
}
const willReturn = []
let counter = 0
while (counter < listOrString.length){
willReturn.push(listOrString.slice(counter, counter += sliceLength))
}
return willReturn
}
```
Tests
```javascript
import { splitEvery } from './splitEvery.js'
test('happy', () => {
expect(splitEvery(3, [ 1, 2, 3, 4, 5, 6, 7 ])).toEqual([
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7 ],
])
expect(splitEvery(3)('foobarbaz')).toEqual([ 'foo', 'bar', 'baz' ])
})
test('with bad input', () => {
expect(() =>
expect(splitEvery(0)('foo')).toEqual([ 'f', 'o', 'o' ])).toThrowErrorMatchingInlineSnapshot('"First argument to splitEvery must be a positive integer"')
})
```
TypeScript test
```typescript
import {splitEvery} from 'rambda'
const list = [1, 2, 3, 4, 5, 6, 7]
describe('R.splitEvery', () => {
it('happy', () => {
const result = splitEvery(3, list)
result // $ExpectType number[][]
})
it('curried', () => {
const result = splitEvery(3)(list)
result // $ExpectType number[][]
})
})
```
[](#splitEvery)
### splitWhen
```typescript
splitWhen(predicate: Predicate, list: U[]): (U[])[]
```
It splits `list` to two arrays according to a `predicate` function.
The first array contains all members of `list` before `predicate` returns `true`.
Try this R.splitWhen example in Rambda REPL
All TypeScript definitions
```typescript
splitWhen(predicate: Predicate, list: U[]): (U[])[];
splitWhen(predicate: Predicate): (list: U[]) => (U[])[];
```
R.splitWhen source
```javascript
export function splitWhen(predicate, input){
if (arguments.length === 1){
return _input => splitWhen(predicate, _input)
}
if (!input)
throw new TypeError(`Cannot read property 'length' of ${ input }`)
const preFound = []
const postFound = []
let found = false
let counter = -1
while (counter++ < input.length - 1){
if (found){
postFound.push(input[ counter ])
} else if (predicate(input[ counter ])){
postFound.push(input[ counter ])
found = true
} else {
preFound.push(input[ counter ])
}
}
return [ preFound, postFound ]
}
```
Tests
```javascript
import { splitWhen as splitWhenRamda } from 'ramda'
import { equals } from './equals.js'
import { splitWhen } from './splitWhen.js'
const list = [ 1, 2, 1, 2 ]
test('happy', () => {
const result = splitWhen(equals(2), list)
expect(result).toEqual([ [ 1 ], [ 2, 1, 2 ] ])
})
test('when predicate returns false', () => {
const result = splitWhen(equals(3))(list)
expect(result).toEqual([ list, [] ])
})
const badInputs = [ 1, true, /foo/g, {} ]
const throwingBadInputs = [ null, undefined ]
test('with bad inputs', () => {
throwingBadInputs.forEach(badInput => {
expect(() => splitWhen(equals(2), badInput)).toThrowWithMessage(TypeError,
`Cannot read property 'length' of ${ badInput }`)
expect(() => splitWhenRamda(equals(2), badInput)).toThrowWithMessage(TypeError,
`Cannot read properties of ${ badInput } (reading 'length')`)
})
badInputs.forEach(badInput => {
const result = splitWhen(equals(2), badInput)
const ramdaResult = splitWhenRamda(equals(2), badInput)
expect(result).toEqual(ramdaResult)
})
})
```
TypeScript test
```typescript
import {splitWhen} from 'rambda'
const list = [1, 2, 1, 2]
const predicate = (x: number) => x === 2
describe('R.splitWhen', () => {
it('happy', () => {
const result = splitWhen(predicate, list)
result // $ExpectType number[][]
})
it('curried', () => {
const result = splitWhen(predicate)(list)
result // $ExpectType number[][]
})
})
```
[](#splitWhen)
### startsWith
```typescript
startsWith(question: T, input: string): boolean
```
When iterable is a string, then it behaves as `String.prototype.startsWith`.
When iterable is a list, then it uses R.equals to determine if the target list starts in the same way as the given target.
Try this R.startsWith example in Rambda REPL
All TypeScript definitions
```typescript
startsWith(question: T, input: string): boolean;
startsWith(question: T): (input: string) => boolean;
startsWith(question: T[], input: T[]): boolean;
startsWith(question: T[]): (input: T[]) => boolean;
```
R.startsWith source
```javascript
import { isArray } from './_internals/isArray.js'
import { equals } from './equals.js'
export function startsWith(question, iterable){
if (arguments.length === 1)
return _iterable => startsWith(question, _iterable)
if (typeof iterable === 'string'){
return iterable.startsWith(question)
}
if (!isArray(question)) return false
let correct = true
const filtered = question.filter((x, index) => {
if (!correct) return false
const result = equals(x, iterable[ index ])
if (!result) correct = false
return result
})
return filtered.length === question.length
}
```
Tests
```javascript
import { startsWith as startsWithRamda } from 'ramda'
import { compareCombinations } from './_internals/testUtils.js'
import { possibleIterables, possibleTargets } from './endsWith.spec.js'
import { startsWith } from './startsWith.js'
test('with string', () => {
expect(startsWith('foo', 'foo-bar')).toBeTrue()
expect(startsWith('baz')('foo-bar')).toBeFalse()
})
test('use R.equals with array', () => {
const list = [ { a : 1 }, { a : 2 }, { a : 3 } ]
expect(startsWith({ a : 1 }, list)).toBeFalse()
expect(startsWith([ { a : 1 } ], list)).toBeTrue()
expect(startsWith([ { a : 1 }, { a : 2 } ], list)).toBeTrue()
expect(startsWith(list, list)).toBeTrue()
expect(startsWith([ { a : 2 } ], list)).toBeFalse()
})
describe('brute force', () => {
compareCombinations({
fn : startsWith,
fnRamda : startsWithRamda,
firstInput : possibleTargets,
secondInput : possibleIterables,
callback : errorsCounters => {
expect(errorsCounters).toMatchInlineSnapshot(`
{
"ERRORS_MESSAGE_MISMATCH": 0,
"ERRORS_TYPE_MISMATCH": 0,
"RESULTS_MISMATCH": 0,
"SHOULD_NOT_THROW": 0,
"SHOULD_THROW": 0,
"TOTAL_TESTS": 32,
}
`)
},
})
})
```
TypeScript test
```typescript
import {startsWith} from 'rambda'
describe('R.startsWith - array', () => {
const question = [{a: 1}]
const iterable = [{a: 1}, {a: 2}]
it('happy', () => {
const result = startsWith(question, iterable)
result // $ExpectType boolean
})
it('curried', () => {
const result = startsWith(question)(iterable)
result // $ExpectType boolean
})
})
describe('R.startsWith - string', () => {
const question = 'foo'
const iterable = 'foo bar'
it('happy', () => {
const result = startsWith(question, iterable)
result // $ExpectType boolean
})
it('curried', () => {
const result = startsWith(question)(iterable)
result // $ExpectType boolean
})
})
```
[](#startsWith)
### subtract
Curried version of `x - y`
Try this R.subtract example in Rambda REPL
[](#subtract)
### sum
```typescript
sum(list: number[]): number
```
Try this R.sum example in Rambda REPL
All TypeScript definitions
```typescript
sum(list: number[]): number;
```
R.sum source
```javascript
export function sum(list){
return list.reduce((prev, current) => prev + current, 0)
}
```
Tests
```javascript
import { sum } from './sum.js'
test('happy', () => {
expect(sum([ 1, 2, 3, 4, 5 ])).toBe(15)
})
```
[](#sum)
### swap
Try this R.swap example in Rambda REPL
[](#swap)
### symmetricDifference
```typescript
symmetricDifference(x: T[], y: T[]): T[]
```
It returns a merged list of `x` and `y` with all equal elements removed.
`R.equals` is used to determine equality.
Try this R.symmetricDifference example in Rambda REPL
All TypeScript definitions
```typescript
symmetricDifference(x: T[], y: T[]): T[];
symmetricDifference(x: T[]): (y: T[]) => T[];
```
R.symmetricDifference source
```javascript
import { concat } from './concat.js'
import { filter } from './filter.js'
import { includes } from './includes.js'
export function symmetricDifference(x, y){
if (arguments.length === 1){
return _y => symmetricDifference(x, _y)
}
return concat(filter(value => !includes(value, y), x),
filter(value => !includes(value, x), y))
}
```
Tests
```javascript
import { symmetricDifference } from './symmetricDifference.js'
test('symmetricDifference', () => {
const list1 = [ 1, 2, 3, 4 ]
const list2 = [ 3, 4, 5, 6 ]
expect(symmetricDifference(list1)(list2)).toEqual([ 1, 2, 5, 6 ])
expect(symmetricDifference([], [])).toEqual([])
})
test('symmetricDifference with objects', () => {
const list1 = [ { id : 1 }, { id : 2 }, { id : 3 }, { id : 4 } ]
const list2 = [ { id : 3 }, { id : 4 }, { id : 5 }, { id : 6 } ]
expect(symmetricDifference(list1)(list2)).toEqual([
{ id : 1 },
{ id : 2 },
{ id : 5 },
{ id : 6 },
])
})
```
TypeScript test
```typescript
import {symmetricDifference} from 'rambda'
describe('R.symmetricDifference', () => {
it('happy', () => {
const list1 = [1, 2, 3, 4]
const list2 = [3, 4, 5, 6]
const result = symmetricDifference(list1, list2)
result // $ExpectType number[]
})
it('curried', () => {
const list1 = [{id: 1}, {id: 2}, {id: 3}, {id: 4}]
const list2 = [{id: 3}, {id: 4}, {id: 5}, {id: 6}]
const result = symmetricDifference(list1)(list2)
result // $ExpectType { id: number; }[]
})
})
```
[](#symmetricDifference)
### T
```typescript
T(): boolean
```
Try this R.T example in Rambda REPL
All TypeScript definitions
```typescript
T(): boolean;
```
R.T source
```javascript
export function T(){
return true
}
```
[](#T)
### tail
```typescript
tail(input: T): T extends [any, ...infer U] ? U : [...T]
```
It returns all but the first element of `input`.
Try this R.tail example in Rambda REPL
All TypeScript definitions
```typescript
tail(input: T): T extends [any, ...infer U] ? U : [...T];
tail(input: string): string;
```
R.tail source
```javascript
import { drop } from './drop.js'
export function tail(listOrString){
return drop(1, listOrString)
}
```
Tests
```javascript
import { tail } from './tail.js'
test('tail', () => {
expect(tail([ 1, 2, 3 ])).toEqual([ 2, 3 ])
expect(tail([ 1, 2 ])).toEqual([ 2 ])
expect(tail([ 1 ])).toEqual([])
expect(tail([])).toEqual([])
expect(tail('abc')).toBe('bc')
expect(tail('ab')).toBe('b')
expect(tail('a')).toBe('')
expect(tail('')).toBe('')
})
```
TypeScript test
```typescript
import {tail} from 'rambda'
describe('R.tail', () => {
it('with string', () => {
const result = tail('foo')
result // $ExpectType string
})
it('with list - one type', () => {
const result = tail([1, 2, 3])
result // $ExpectType number[]
})
it('with list - mixed types', () => {
const result = tail(['foo', 'bar', 1, 2, 3])
result // $ExpectType (string | number)[]
})
})
```
[](#tail)
### take
```typescript
take(howMany: number, input: T): T extends string ? string : T
```
It returns the first `howMany` elements of `input`.
Try this R.take example in Rambda REPL
All TypeScript definitions
```typescript
take(howMany: number, input: T): T extends string ? string : T;
take(howMany: number) : (input: T) => T extends string ? string : T;
```
R.take source
```javascript
import baseSlice from './_internals/baseSlice.js'
export function take(howMany, listOrString){
if (arguments.length === 1)
return _listOrString => take(howMany, _listOrString)
if (howMany < 0) return listOrString.slice()
if (typeof listOrString === 'string') return listOrString.slice(0, howMany)
return baseSlice(
listOrString, 0, howMany
)
}
```
Tests
```javascript
import { take } from './take.js'
test('happy', () => {
const arr = [ 'foo', 'bar', 'baz' ]
expect(take(1, arr)).toEqual([ 'foo' ])
expect(arr).toEqual([ 'foo', 'bar', 'baz' ])
expect(take(2)([ 'foo', 'bar', 'baz' ])).toEqual([ 'foo', 'bar' ])
expect(take(3, [ 'foo', 'bar', 'baz' ])).toEqual([ 'foo', 'bar', 'baz' ])
expect(take(4, [ 'foo', 'bar', 'baz' ])).toEqual([ 'foo', 'bar', 'baz' ])
expect(take(3)('rambda')).toBe('ram')
})
test('with negative index', () => {
expect(take(-1, [ 1, 2, 3 ])).toEqual([ 1, 2, 3 ])
expect(take(-Infinity, [ 1, 2, 3 ])).toEqual([ 1, 2, 3 ])
})
test('with zero index', () => {
expect(take(0, [ 1, 2, 3 ])).toEqual([])
})
```
TypeScript test
```typescript
import {take} from 'rambda'
const list = [1, 2, 3, 4]
const str = 'foobar'
const howMany = 2
describe('R.take - array', () => {
it('happy', () => {
const result = take(howMany, list)
result // $ExpectType number[]
})
it('curried', () => {
const result = take(howMany)(list)
result // $ExpectType number[]
})
})
describe('R.take - string', () => {
it('happy', () => {
const result = take(howMany, str)
result // $ExpectType string
})
it('curried', () => {
const result = take(howMany)(str)
result // $ExpectType string
})
})
```
[](#take)
### takeLast
```typescript
takeLast(howMany: number, input: T): T extends string ? string : T
```
It returns the last `howMany` elements of `input`.
Try this R.takeLast example in Rambda REPL
All TypeScript definitions
```typescript
takeLast(howMany: number, input: T): T extends string ? string : T;
takeLast(howMany: number) : (input: T) => T extends string ? string : T;
```
R.takeLast source
```javascript
import baseSlice from './_internals/baseSlice.js'
export function takeLast(howMany, listOrString){
if (arguments.length === 1)
return _listOrString => takeLast(howMany, _listOrString)
const len = listOrString.length
if (howMany < 0) return listOrString.slice()
let numValue = howMany > len ? len : howMany
if (typeof listOrString === 'string')
return listOrString.slice(len - numValue)
numValue = len - numValue
return baseSlice(
listOrString, numValue, len
)
}
```
Tests
```javascript
import { takeLast } from './takeLast.js'
test('with arrays', () => {
expect(takeLast(1, [ 'foo', 'bar', 'baz' ])).toEqual([ 'baz' ])
expect(takeLast(2)([ 'foo', 'bar', 'baz' ])).toEqual([ 'bar', 'baz' ])
expect(takeLast(3, [ 'foo', 'bar', 'baz' ])).toEqual([ 'foo', 'bar', 'baz' ])
expect(takeLast(4, [ 'foo', 'bar', 'baz' ])).toEqual([ 'foo', 'bar', 'baz' ])
expect(takeLast(10, [ 'foo', 'bar', 'baz' ])).toEqual([ 'foo', 'bar', 'baz' ])
})
test('with strings', () => {
expect(takeLast(3, 'rambda')).toBe('bda')
expect(takeLast(7, 'rambda')).toBe('rambda')
})
test('with negative index', () => {
expect(takeLast(-1, [ 1, 2, 3 ])).toEqual([ 1, 2, 3 ])
expect(takeLast(-Infinity, [ 1, 2, 3 ])).toEqual([ 1, 2, 3 ])
})
```
TypeScript test
```typescript
import {filter, piped, takeLast} from 'rambda'
const list = [1, 2, 3, 4]
const str = 'foobar'
const howMany = 2
describe('R.takeLast - array', () => {
it('happy', () => {
const result = takeLast(howMany, list)
result // $ExpectType number[]
})
it('curried', () => {
const result = takeLast(howMany)(list)
result // $ExpectType number[]
})
it('real case', () => {
const data = ['foo', 'bar', 'baz', 'qux']
const result = piped(
data,
filter(
x => x.length >= 100
),
takeLast(2),
)
result // $ExpectType string[]
})
})
describe('R.takeLast - string', () => {
it('happy', () => {
const result = takeLast(howMany, str)
result // $ExpectType string
})
it('curried', () => {
const result = takeLast(howMany)(str)
result // $ExpectType string
})
})
```
[](#takeLast)
### takeLastWhile
```typescript
takeLastWhile(predicate: (x: string) => boolean, input: string): string
```
Try this R.takeLastWhile example in Rambda REPL
All TypeScript definitions
```typescript
takeLastWhile(predicate: (x: string) => boolean, input: string): string;
takeLastWhile(predicate: (x: string) => boolean): (input: string) => string;
takeLastWhile(predicate: (x: T) => boolean, input: T[]): T[];
takeLastWhile(predicate: (x: T) => boolean): (input: T[]) => T[];
```
R.takeLastWhile source
```javascript
import { isArray } from './_internals/isArray.js'
export function takeLastWhile(predicate, input){
if (arguments.length === 1){
return _input => takeLastWhile(predicate, _input)
}
if (input.length === 0) return input
const toReturn = []
let counter = input.length
while (counter){
const item = input[ --counter ]
if (!predicate(item)){
break
}
toReturn.push(item)
}
return isArray(input) ? toReturn.reverse() : toReturn.reverse().join('')
}
```
Tests
```javascript
import { takeLastWhile } from './takeLastWhile.js'
const assert = require('assert')
const list = [ 1, 2, 3, 4 ]
test('happy', () => {
const predicate = x => x > 2
const result = takeLastWhile(predicate, list)
expect(result).toEqual([ 3, 4 ])
})
test('predicate is always true', () => {
const predicate = () => true
const result = takeLastWhile(predicate)(list)
expect(result).toEqual(list)
})
test('predicate is always false', () => {
const predicate = () => false
const result = takeLastWhile(predicate, list)
expect(result).toEqual([])
})
test('with string', () => {
const result = takeLastWhile(x => x !== 'F', 'FOOBAR')
expect(result).toBe('OOBAR')
})
```
TypeScript test
```typescript
import {takeLastWhile} from 'rambda'
const list = [1, 2, 3]
const str = 'FOO'
describe('R.takeLastWhile', () => {
it('with array', () => {
const result = takeLastWhile(x => x > 1, list)
result // $ExpectType number[]
})
it('with array - curried', () => {
const result = takeLastWhile(x => x > 1, list)
result // $ExpectType number[]
})
it('with string', () => {
const result = takeLastWhile(x => x !== 'F', str)
result // $ExpectType string
})
it('with string - curried', () => {
const result = takeLastWhile(x => x !== 'F')(str)
result // $ExpectType string
})
})
```
[](#takeLastWhile)
### takeWhile
Try this R.takeWhile example in Rambda REPL
[](#takeWhile)
### tap
```typescript
tap(fn: (x: T) => void, input: T): T
```
It applies function `fn` to input `x` and returns `x`.
One use case is debugging in the middle of `R.compose`.
Try this R.tap example in Rambda REPL
All TypeScript definitions
```typescript
tap(fn: (x: T) => void, input: T): T;
tap(fn: (x: T) => void): (input: T) => T;
```
R.tap source
```javascript
export function tap(fn, x){
if (arguments.length === 1) return _x => tap(fn, _x)
fn(x)
return x
}
```
Tests
```javascript
import { tap } from './tap.js'
test('tap', () => {
let a = 1
const sayX = x => a = x
expect(tap(sayX, 100)).toBe(100)
expect(tap(sayX)(100)).toBe(100)
expect(a).toBe(100)
})
```
TypeScript test
```typescript
import {tap, pipe} from 'rambda'
describe('R.tap', () => {
it('happy', () => {
pipe(
tap(x => {
x // $ExpectType number[]
}),
(x: number[]) => x.length
)([1, 2])
})
})
```
[](#tap)
### test
```typescript
test(regExpression: RegExp): (str: string) => boolean
```
It determines whether `str` matches `regExpression`.
Try this R.test example in Rambda REPL
All TypeScript definitions
```typescript
test(regExpression: RegExp): (str: string) => boolean;
test(regExpression: RegExp, str: string): boolean;
```
R.test source
```javascript
export function test(pattern, str){
if (arguments.length === 1) return _str => test(pattern, _str)
if (typeof pattern === 'string'){
throw new TypeError(`R.test requires a value of type RegExp as its first argument; received "${ pattern }"`)
}
return str.search(pattern) !== -1
}
```
Tests
```javascript
import { test as testMethod } from './test.js'
test('happy', () => {
expect(testMethod(/^x/, 'xyz')).toBeTrue()
expect(testMethod(/^y/)('xyz')).toBeFalse()
})
test('throws if first argument is not regex', () => {
expect(() => testMethod('foo', 'bar')).toThrowErrorMatchingInlineSnapshot('"R.test requires a value of type RegExp as its first argument; received "foo""')
})
```
TypeScript test
```typescript
import {test} from 'rambda'
const input = 'foo '
const regex = /foo/
describe('R.test', () => {
it('happy', () => {
const result = test(regex, input)
result // $ExpectType boolean
})
it('curried', () => {
const result = test(regex)(input)
result // $ExpectType boolean
})
})
```
[](#test)
### times
```typescript
times(fn: (i: number) => T, howMany: number): T[]
```
It returns the result of applying function `fn` over members of range array.
The range array includes numbers between `0` and `howMany`(exclusive).
Try this R.times example in Rambda REPL
All TypeScript definitions
```typescript
times(fn: (i: number) => T, howMany: number): T[];
times(fn: (i: number) => T): (howMany: number) => T[];
```
R.times source
```javascript
import { isInteger } from './_internals/isInteger.js'
import { map } from './map.js'
import { range } from './range.js'
export function times(fn, howMany){
if (arguments.length === 1) return _howMany => times(fn, _howMany)
if (!isInteger(howMany) || howMany < 0){
throw new RangeError('n must be an integer')
}
return map(fn, range(0, howMany))
}
```
Tests
```javascript
import assert from 'assert'
import { identity } from './identity.js'
import { times } from './times.js'
test('happy', () => {
const result = times(identity, 5)
expect(result).toEqual([ 0, 1, 2, 3, 4 ])
})
test('with bad input', () => {
assert.throws(() => {
times(3)('cheers!')
}, RangeError)
assert.throws(() => {
times(identity, -1)
}, RangeError)
})
test('curry', () => {
const result = times(identity)(5)
expect(result).toEqual([ 0, 1, 2, 3, 4 ])
})
```
TypeScript test
```typescript
import {times, identity} from 'rambda'
describe('R.times', () => {
it('happy', () => {
const result = times(identity, 5)
result // $ExpectType number[]
})
})
```
[](#times)
### toLower
```typescript
toLower(str: S): Lowercase
```
Try this R.toLower example in Rambda REPL
All TypeScript definitions
```typescript
toLower(str: S): Lowercase;
toLower(str: string): string;
```
R.toLower source
```javascript
export function toLower(str){
return str.toLowerCase()
}
```
Tests
```javascript
import { toLower } from './toLower.js'
test('toLower', () => {
expect(toLower('FOO|BAR|BAZ')).toBe('foo|bar|baz')
})
```
[](#toLower)
### toPairs
```typescript
toPairs>(obj: O): Array<{ [key in K]: [`${key}`, O[key]] }[K]>
```
It transforms an object to a list.
Try this R.toPairs example in Rambda REPL
All TypeScript definitions
```typescript
toPairs>(obj: O): Array<{ [key in K]: [`${key}`, O[key]] }[K]>;
toPairs(obj: Record): Array<[string, S]>;
```
R.toPairs source
```javascript
export function toPairs(obj){
return Object.entries(obj)
}
```
Tests
```javascript
import { toPairs } from './toPairs.js'
const obj = {
a : 1,
b : 2,
c : [ 3, 4 ],
}
const expected = [
[ 'a', 1 ],
[ 'b', 2 ],
[ 'c', [ 3, 4 ] ],
]
test('happy', () => {
expect(toPairs(obj)).toEqual(expected)
})
```
[](#toPairs)
### toString
```typescript
toString(x: unknown): string
```
Try this R.toString example in Rambda REPL
All TypeScript definitions
```typescript
toString(x: unknown): string;
```
R.toString source
```javascript
export function toString(x){
return x.toString()
}
```
Tests
```javascript
import { toString } from './toString.js'
test('happy', () => {
expect(toString([ 1, 2, 3 ])).toBe('1,2,3')
})
```
[](#toString)
### toUpper
```typescript
toUpper(str: S): Uppercase
```
Try this R.toUpper example in Rambda REPL
All TypeScript definitions
```typescript
toUpper(str: S): Uppercase;
toUpper(str: string): string;
```
R.toUpper source
```javascript
export function toUpper(str){
return str.toUpperCase()
}
```
Tests
```javascript
import { toUpper } from './toUpper.js'
test('toUpper', () => {
expect(toUpper('foo|bar|baz')).toBe('FOO|BAR|BAZ')
})
```
[](#toUpper)
### transpose
```typescript
transpose(list: (T[])[]): (T[])[]
```
Try this R.transpose example in Rambda REPL
All TypeScript definitions
```typescript
transpose(list: (T[])[]): (T[])[];
```
R.transpose source
```javascript
import { isArray } from './_internals/isArray.js'
export function transpose(array){
return array.reduce((acc, el) => {
el.forEach((nestedEl, i) =>
isArray(acc[ i ]) ? acc[ i ].push(nestedEl) : acc.push([ nestedEl ]))
return acc
}, [])
}
```
Tests
```javascript
import { transpose } from './transpose.js'
test('happy', () => {
const input = [
[ 'a', 1 ],
[ 'b', 2 ],
[ 'c', 3 ],
]
expect(transpose(input)).toEqual([
[ 'a', 'b', 'c' ],
[ 1, 2, 3 ],
])
})
test('when rows are shorter', () => {
const actual = transpose([ [ 10, 11 ], [ 20 ], [], [ 30, 31, 32 ] ])
const expected = [ [ 10, 20, 30 ], [ 11, 31 ], [ 32 ] ]
expect(actual).toEqual(expected)
})
test('with empty array', () => {
expect(transpose([])).toEqual([])
})
test('array with falsy values', () => {
const actual = transpose([
[ true, false, undefined, null ],
[ null, undefined, false, true ],
])
const expected = [
[ true, null ],
[ false, undefined ],
[ undefined, false ],
[ null, true ],
]
expect(actual).toEqual(expected)
})
```
TypeScript test
```typescript
import {transpose} from 'rambda'
const input = [
['a', 1],
['b', 2],
['c', 3],
]
describe('R.transpose', () => {
it('happy', () => {
const result = transpose(input)
result // $ExpectType (string | number)[][]
})
})
```
[](#transpose)
### trim
```typescript
trim(str: string): string
```
Try this R.trim example in Rambda REPL
All TypeScript definitions
```typescript
trim(str: string): string;
```
R.trim source
```javascript
export function trim(str){
return str.trim()
}
```
Tests
```javascript
import { trim } from './trim.js'
test('trim', () => {
expect(trim(' foo ')).toBe('foo')
})
```
[](#trim)
### tryCatch
It 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).
Try this R.tryCatch example in Rambda REPL
[](#tryCatch)
### type
It accepts any input and it returns its type.
Try this R.type example in Rambda REPL
[](#type)
### unapply
```typescript
unapply(fn: (args: any[]) => T): (...args: any[]) => T
```
It calls a function `fn` with the list of values of the returned function.
`R.unapply` is the opposite of `R.apply` method.
Try this R.unapply example in Rambda REPL
All TypeScript definitions
```typescript
unapply(fn: (args: any[]) => T): (...args: any[]) => T;
```
R.unapply source
```javascript
export function unapply(fn){
return function (...args){
return fn.call(this, args)
}
}
```
Tests
```javascript
import { apply } from './apply.js'
import { converge } from './converge.js'
import { identity } from './identity.js'
import { prop } from './prop.js'
import { sum } from './sum.js'
import { unapply } from './unapply.js'
test('happy', () => {
const fn = unapply(identity)
expect(fn(
1, 2, 3
)).toEqual([ 1, 2, 3 ])
expect(fn()).toEqual([])
})
test('returns a function which is always passed one argument', () => {
const fn = unapply(function (){
return arguments.length
})
expect(fn('x')).toBe(1)
expect(fn('x', 'y')).toBe(1)
expect(fn(
'x', 'y', 'z'
)).toBe(1)
})
test('forwards arguments to decorated function as an array', () => {
const fn = unapply(xs => '[' + xs + ']')
expect(fn(2)).toBe('[2]')
expect(fn(2, 4)).toBe('[2,4]')
expect(fn(
2, 4, 6
)).toBe('[2,4,6]')
})
test('returns a function with length 0', () => {
const fn = unapply(identity)
expect(fn).toHaveLength(0)
})
test('is the inverse of R.apply', () => {
let a, b, c, d, e, f, g, n
const rand = function (){
return Math.floor(200 * Math.random()) - 100
}
f = Math.max
g = unapply(apply(f))
n = 1
while (n <= 100){
a = rand()
b = rand()
c = rand()
d = rand()
e = rand()
expect(f(
a, b, c, d, e
)).toEqual(g(
a, b, c, d, e
))
n += 1
}
f = function (xs){
return '[' + xs + ']'
}
g = apply(unapply(f))
n = 1
while (n <= 100){
a = rand()
b = rand()
c = rand()
d = rand()
e = rand()
expect(f([ a, b, c, d, e ])).toEqual(g([ a, b, c, d, e ]))
n += 1
}
})
test('it works with converge', () => {
const fn = unapply(sum)
const convergeFn = converge(fn, [ prop('a'), prop('b'), prop('c') ])
const obj = {
a : 1337,
b : 42,
c : 1,
}
const expected = 1337 + 42 + 1
expect(convergeFn(obj)).toEqual(expected)
})
```
TypeScript test
```typescript
import {join, unapply, sum} from 'rambda'
describe('R.unapply', () => {
it('happy', () => {
const fn = unapply(sum)
fn(1, 2, 3) // $ExpectType number
})
it('joins a string', () => {
const fn = unapply(join(''))
fn('s', 't', 'r', 'i', 'n', 'g') // $ExpectType string
})
})
```
[](#unapply)
### union
```typescript
union(x: T[], y: T[]): T[]
```
It takes two lists and return a new list containing a merger of both list with removed duplicates.
`R.equals` is used to compare for duplication.
Try this R.union example in Rambda REPL
All TypeScript definitions
```typescript
union(x: T[], y: T[]): T[];
union(x: T[]): (y: T[]) => T[];
```
R.union source
```javascript
import { cloneList } from './_internals/cloneList.js'
import { includes } from './includes.js'
export function union(x, y){
if (arguments.length === 1) return _y => union(x, _y)
const toReturn = cloneList(x)
y.forEach(yInstance => {
if (!includes(yInstance, x)) toReturn.push(yInstance)
})
return toReturn
}
```
Tests
```javascript
import { union } from './union.js'
test('happy', () => {
expect(union([ 1, 2 ], [ 2, 3 ])).toEqual([ 1, 2, 3 ])
})
test('with list of objects', () => {
const list1 = [ { a : 1 }, { a : 2 } ]
const list2 = [ { a : 2 }, { a : 3 } ]
const result = union(list1)(list2)
})
```
TypeScript test
```typescript
import {union} from 'rambda'
describe('R.union', () => {
it('happy', () => {
const result = union([1, 2], [2, 3])
result // $ExpectType number[]
})
it('with array of objects - case 1', () => {
const list1 = [{a: 1}, {a: 2}]
const list2 = [{a: 2}, {a: 3}]
const result = union(list1, list2)
result // $ExpectType { a: number; }[]
})
it('with array of objects - case 2', () => {
const list1 = [{a: 1, b: 1}, {a: 2}]
const list2 = [{a: 2}, {a: 3, b: 3}]
const result = union(list1, list2)
result[0].a // $ExpectType number
result[0].b // $ExpectType number | undefined
})
})
describe('R.union - curried', () => {
it('happy', () => {
const result = union([1, 2])([2, 3])
result // $ExpectType number[]
})
it('with array of objects - case 1', () => {
const list1 = [{a: 1}, {a: 2}]
const list2 = [{a: 2}, {a: 3}]
const result = union(list1)(list2)
result // $ExpectType { a: number; }[]
})
it('with array of objects - case 2', () => {
const list1 = [{a: 1, b: 1}, {a: 2}]
const list2 = [{a: 2}, {a: 3, b: 3}]
const result = union(list1)(list2)
result[0].a // $ExpectType number
result[0].b // $ExpectType number | undefined
})
})
```
[](#union)
### uniq
```typescript
uniq(list: T[]): T[]
```
It returns a new array containing only one copy of each element of `list`.
`R.equals` is used to determine equality.
Try this R.uniq example in Rambda REPL
All TypeScript definitions
```typescript
uniq(list: T[]): T[];
```
R.uniq source
```javascript
import { _Set } from './_internals/set.js'
export function uniq(list){
const set = new _Set()
const willReturn = []
list.forEach(item => {
if (set.checkUniqueness(item)){
willReturn.push(item)
}
})
return willReturn
}
```
Tests
```javascript
import { uniq } from './uniq.js'
test('happy', () => {
const list = [ 1, 2, 3, 3, 3, 1, 2, 0 ]
expect(uniq(list)).toEqual([ 1, 2, 3, 0 ])
})
test('with object', () => {
const list = [ { a : 1 }, { a : 2 }, { a : 1 }, { a : 2 } ]
expect(uniq(list)).toEqual([ { a : 1 }, { a : 2 } ])
})
test('with nested array', () => {
expect(uniq([ [ 42 ], [ 42 ] ])).toEqual([ [ 42 ] ])
})
test('with booleans', () => {
expect(uniq([ [ false ], [ false ], [ true ] ])).toEqual([ [ false ], [ true ] ])
})
test('with falsy values', () => {
expect(uniq([ undefined, null ])).toEqual([ undefined, null ])
})
test('can distinct between string and number', () => {
expect(uniq([ 1, '1' ])).toEqual([ 1, '1' ])
})
```
TypeScript test
```typescript
import {uniq} from 'rambda'
describe('R.uniq', () => {
it('happy', () => {
const result = uniq([1, 2, 3, 3, 3, 1, 2, 0])
result // $ExpectType number[]
})
})
```
[](#uniq)
### uniqBy
It applies uniqueness to input list based on function that defines what to be used for comparison between elements.
`R.equals` is used to determine equality.
Try this R.uniqBy example in Rambda REPL
[](#uniqBy)
### uniqWith
```typescript
uniqWith(predicate: (x: T, y: T) => boolean, list: T[]): T[]
```
It returns a new array containing only one copy of each element in `list` according to `predicate` function.
This predicate should return true, if two elements are equal.
Try this R.uniqWith example in Rambda REPL
All TypeScript definitions
```typescript
uniqWith(predicate: (x: T, y: T) => boolean, list: T[]): T[];
uniqWith(predicate: (x: T, y: T) => boolean): (list: T[]) => T[];
```
R.uniqWith source
```javascript
function includesWith(
predicate, target, list
){
let willReturn = false
let index = -1
while (++index < list.length && !willReturn){
const value = list[ index ]
if (predicate(target, value)){
willReturn = true
}
}
return willReturn
}
export function uniqWith(predicate, list){
if (arguments.length === 1) return _list => uniqWith(predicate, _list)
let index = -1
const willReturn = []
while (++index < list.length){
const value = list[ index ]
if (!includesWith(
predicate, value, willReturn
)){
willReturn.push(value)
}
}
return willReturn
}
```
Tests
```javascript
import { uniqWith as uniqWithRamda } from 'ramda'
import { uniqWith } from './uniqWith.js'
const list = [ { a : 1 }, { a : 1 } ]
test('happy', () => {
const fn = (x, y) => x.a === y.a
const result = uniqWith(fn, list)
expect(result).toEqual([ { a : 1 } ])
})
test('with list of strings', () => {
const fn = (x, y) => x.length === y.length
const list = [ '0', '11', '222', '33', '4', '55' ]
const result = uniqWith(fn)(list)
const resultRamda = uniqWithRamda(fn, list)
expect(result).toEqual([ '0', '11', '222' ])
expect(resultRamda).toEqual([ '0', '11', '222' ])
})
```
TypeScript test
```typescript
import {uniqWith} from 'rambda'
describe('R.uniqWith', () => {
it('happy', () => {
const list = [{a: 1}, {a: 1}]
const fn = (x: any, y: any) => x.a === y.a
const result = uniqWith(fn, list)
result // $ExpectType { a: number; }[]
})
})
```
[](#uniqWith)
### unless
```typescript
unless(predicate: (x: T) => boolean, whenFalseFn: (x: T) => U, x: T): T | U
```
The method returns function that will be called with argument `input`.
If `predicate(input)` returns `false`, then the end result will be the outcome of `whenFalse(input)`.
In the other case, the final output will be the `input` itself.
Try this R.unless example in Rambda REPL
All TypeScript definitions
```typescript
unless(predicate: (x: T) => boolean, whenFalseFn: (x: T) => U, x: T): T | U;
unless(predicate: (x: T) => boolean, whenFalseFn: (x: T) => U): (x: T) => T | U;
unless(predicate: (x: T) => boolean, whenFalseFn: (x: T) => T, x: T): T;
unless(predicate: (x: T) => boolean, whenFalseFn: (x: T) => T): (x: T) => T;
```
R.unless source
```javascript
import { curry } from './curry.js'
function unlessFn(
predicate, whenFalseFn, input
){
if (predicate(input)) return input
return whenFalseFn(input)
}
export const unless = curry(unlessFn)
```
Tests
```javascript
import { inc } from './inc.js'
import { isNil } from './isNil.js'
import { unless } from './unless.js'
test('happy', () => {
const safeInc = unless(isNil, inc)
expect(safeInc(null)).toBeNull()
expect(safeInc(1)).toBe(2)
})
test('curried', () => {
const safeIncCurried = unless(isNil)(inc)
expect(safeIncCurried(null)).toBeNull()
})
test('with 3 inputs', () => {
let result = unless(x => x.startsWith('/'), x=> x.concat('/'), '/api')
expect(result).toBe('/api')
})
```
TypeScript test
```typescript
import {unless, inc} from 'rambda'
describe('R.unless', () => {
it('happy', () => {
const fn = unless(x => x > 5, inc)
const result = fn(1)
result // $ExpectType number
})
it('with one explicit type', () => {
const result = unless(
x => {
x // $ExpectType number
return x > 5
},
x => {
x // $ExpectType number
return x + 1
},
1
)
result // $ExpectType number
})
it('with two different explicit types', () => {
const result = unless(
x => {
x // $ExpectType number
return x > 5
},
x => {
x // $ExpectType number
return `${x}-foo`
},
1
)
result // $ExpectType string | number
})
})
describe('R.unless - curried', () => {
it('happy', () => {
const fn = unless(x => x > 5, inc)
const result = fn(1)
result // $ExpectType number
})
it('with one explicit type', () => {
const fn = unless(
x => {
x // $ExpectType number
return x > 5
},
x => {
x // $ExpectType number
return x + 1
}
)
const result = fn(1)
result // $ExpectType number
})
it('with two different explicit types', () => {
const fn = unless(
x => {
x // $ExpectType number
return x > 5
},
x => {
x // $ExpectType number
return `${x}-foo`
}
)
const result = fn(1)
result // $ExpectType string | number
})
})
```
[](#unless)
### unnest
Try this R.unnest example in Rambda REPL
[](#unnest)
### unwind
Try this R.unwind example in Rambda REPL
[](#unwind)
### update
```typescript
update(index: number, newValue: T, list: T[]): T[]
```
It returns a copy of `list` with updated element at `index` with `newValue`.
Try this R.update example in Rambda REPL
All TypeScript definitions
```typescript
update(index: number, newValue: T, list: T[]): T[];
update(index: number, newValue: T): (list: T[]) => T[];
```
R.update source
```javascript
import { cloneList } from './_internals/cloneList.js'
import { curry } from './curry.js'
export function updateFn(
index, newValue, list
){
const clone = cloneList(list)
if (index === -1) return clone.fill(newValue, index)
return clone.fill(
newValue, index, index + 1
)
}
export const update = curry(updateFn)
```
Tests
```javascript
import { update } from './update.js'
const list = [ 1, 2, 3 ]
test('happy', () => {
const newValue = 8
const index = 1
const result = update(
index, newValue, list
)
const curriedResult = update(index, newValue)(list)
const tripleCurriedResult = update(index)(newValue)(list)
const expected = [ 1, 8, 3 ]
expect(result).toEqual(expected)
expect(curriedResult).toEqual(expected)
expect(tripleCurriedResult).toEqual(expected)
})
test('list has no such index', () => {
const newValue = 8
const index = 10
const result = update(
index, newValue, list
)
expect(result).toEqual(list)
})
test('with negative index', () => {
expect(update(
-1, 10, [ 1 ]
)).toEqual([ 10 ])
expect(update(
-1, 10, []
)).toEqual([])
expect(update(
-1, 10, list
)).toEqual([ 1, 2, 10 ])
expect(update(
-2, 10, list
)).toEqual([ 1, 10, 3 ])
expect(update(
-3, 10, list
)).toEqual([ 10, 2, 3 ])
})
```
TypeScript test
```typescript
import {update} from 'rambda'
describe('R.update', () => {
it('happy', () => {
const result = update(1, 0, [1, 2, 3])
result // $ExpectType number[]
})
})
```
[](#update)
### values
```typescript
values(obj: T): T[K][]
```
With correct input, this is nothing more than `Object.values(Record)`. If `obj` is not an object, then it returns an empty array.
Try this R.values example in Rambda REPL
All TypeScript definitions
```typescript
values(obj: T): T[K][];
```
R.values source
```javascript
import { type } from './type.js'
export function values(obj){
if (type(obj) !== 'Object') return []
return Object.values(obj)
}
```
Tests
```javascript
import { values } from './values.js'
test('happy', () => {
expect(values({
a : 1,
b : 2,
c : 3,
})).toEqual([ 1, 2, 3 ])
})
test('with bad input', () => {
expect(values(null)).toEqual([])
expect(values(undefined)).toEqual([])
expect(values(55)).toEqual([])
expect(values('foo')).toEqual([])
expect(values(true)).toEqual([])
expect(values(false)).toEqual([])
expect(values(NaN)).toEqual([])
expect(values(Infinity)).toEqual([])
expect(values([])).toEqual([])
})
```
TypeScript test
```typescript
import {values} from 'rambda'
describe('R.values', () => {
it('happy', () => {
const result = values({
a: 1,
b: 2,
c: 3,
})
result // $ExpectType number[]
})
})
```
[](#values)
### view
```typescript
view(lens: Lens): (obj: S) => A
```
It returns the value of `lens` focus over `target` object.
Try this R.view example in Rambda REPL
All TypeScript definitions
```typescript
view(lens: Lens): (obj: S) => A;
view(lens: Lens, obj: S): A;
```
R.view source
```javascript
const Const = x => ({
x,
map : fn => Const(x),
})
export function view(lens, target){
if (arguments.length === 1) return _target => view(lens, _target)
return lens(Const)(target).x
}
```
Tests
```javascript
import { assoc } from './assoc.js'
import { lens } from './lens.js'
import { prop } from './prop.js'
import { view } from './view.js'
const testObject = { foo : 'Led Zeppelin' }
const assocLens = lens(prop('foo'), assoc('foo'))
test('happy', () => {
expect(view(assocLens, testObject)).toBe('Led Zeppelin')
})
```
[](#view)
### when
```typescript
when(predicate: (x: T) => boolean, whenTrueFn: (a: T) => U, input: T): T | U
```
It pass `input` to `predicate` function and if the result is `true`, it will return the result of `whenTrueFn(input)`.
If the `predicate` returns `false`, then it will simply return `input`.
Try this R.when example in Rambda REPL
All TypeScript definitions
```typescript
when(predicate: (x: T) => boolean, whenTrueFn: (a: T) => U, input: T): T | U;
when(predicate: (x: T) => boolean, whenTrueFn: (a: T) => U): (input: T) => T | U;
when(predicate: (x: T) => boolean): ((whenTrueFn: (a: T) => U) => (input: T) => T | U);
```
R.when source
```javascript
import { curry } from './curry.js'
function whenFn(
predicate, whenTrueFn, input
){
if (!predicate(input)) return input
return whenTrueFn(input)
}
export const when = curry(whenFn)
```
Tests
```javascript
import { add } from './add.js'
import { when } from './when.js'
const predicate = x => typeof x === 'number'
test('happy', () => {
const fn = when(predicate, add(11))
expect(fn(11)).toBe(22)
expect(fn('foo')).toBe('foo')
})
```
TypeScript test
```typescript
import {when} from 'rambda'
const predicate = (x: number) => x > 2
const whenTrueFn = (x: number) => String(x)
describe('R.when', () => {
it('happy', () => {
const result = when(predicate, whenTrueFn, 1)
result // $ExpectType string | 1
})
it('curry 1', () => {
const fn = when(predicate, whenTrueFn)
const result = fn(1)
result // $ExpectType string | number
})
it('curry 2 require explicit types', () => {
const fn = when(predicate)(whenTrueFn)
const result = fn(1)
result // $ExpectType string | number
})
})
```
[](#when)
### where
```typescript
where(conditions: T, input: U): boolean
```
It returns `true` if all each property in `conditions` returns `true` when applied to corresponding property in `input` object.
Try this R.where example in Rambda REPL
All TypeScript definitions
```typescript
where(conditions: T, input: U): boolean;
where(conditions: T): (input: U) => boolean;
where(conditions: ObjFunc2, input: U): boolean;
where(conditions: ObjFunc2): (input: U) => boolean;
```
R.where source
```javascript
export function where(conditions, input){
if (input === undefined){
return _input => where(conditions, _input)
}
let flag = true
for (const prop in conditions){
if (!flag) continue
const result = conditions[ prop ](input[ prop ])
if (flag && result === false){
flag = false
}
}
return flag
}
```
Tests
```javascript
import { equals } from './equals.js'
import { where } from './where.js'
test('when true', () => {
const result = where({
a : equals('foo'),
b : equals('bar'),
},
{
a : 'foo',
b : 'bar',
x : 11,
y : 19,
})
expect(result).toBeTrue()
})
test('when false | early exit', () => {
let counter = 0
const equalsFn = expected => input => {
console.log(expected, 'expected')
counter++
return input === expected
}
const predicate = where({
a : equalsFn('foo'),
b : equalsFn('baz'),
})
expect(predicate({
a : 'notfoo',
b : 'notbar',
})).toBeFalse()
expect(counter).toBe(1)
})
```
TypeScript test
```typescript
import {where, equals} from 'rambda'
describe('R.where', () => {
it('happy', () => {
const input = {
a: 'foo',
b: 'bar',
x: 11,
y: 19,
}
const conditions = {
a: equals('foo'),
b: equals('bar'),
}
const result = where(conditions, input)
const curriedResult = where(conditions)(input)
result // $ExpectType boolean
curriedResult // $ExpectType boolean
})
})
```
[](#where)
### whereAny
Same as `R.where`, but it will return `true` if at least one condition check returns `true`.
Try this R.whereAny example in Rambda REPL
[](#whereAny)
### whereEq
```typescript
whereEq(condition: T, input: U): boolean
```
It will return `true` if all of `input` object fully or partially include `rule` object.
`R.equals` is used to determine equality.
Try this R.whereEq example in Rambda REPL
All TypeScript definitions
```typescript
whereEq(condition: T, input: U): boolean;
whereEq(condition: T): (input: U) => boolean;
```
R.whereEq source
```javascript
import { equals } from './equals.js'
import { filter } from './filter.js'
export function whereEq(condition, input){
if (arguments.length === 1){
return _input => whereEq(condition, _input)
}
const result = filter((conditionValue, conditionProp) =>
equals(conditionValue, input[ conditionProp ]),
condition)
return Object.keys(result).length === Object.keys(condition).length
}
```
Tests
```javascript
import { whereEq } from './whereEq.js'
test('when true', () => {
const condition = { a : 1 }
const input = {
a : 1,
b : 2,
}
const result = whereEq(condition, input)
const expectedResult = true
expect(result).toEqual(expectedResult)
})
test('when false', () => {
const condition = { a : 1 }
const input = { b : 2 }
const result = whereEq(condition, input)
const expectedResult = false
expect(result).toEqual(expectedResult)
})
test('with nested object', () => {
const condition = { a : { b : 1 } }
const input = {
a : { b : 1 },
c : 2,
}
const result = whereEq(condition)(input)
const expectedResult = true
expect(result).toEqual(expectedResult)
})
test('with wrong input', () => {
const condition = { a : { b : 1 } }
expect(() => whereEq(condition, null)).toThrowErrorMatchingInlineSnapshot('"Cannot read properties of null (reading \'a\')"')
})
```
TypeScript test
```typescript
import {whereEq} from 'rambda'
describe('R.whereEq', () => {
it('happy', () => {
const result = whereEq({a: {b: 2}}, {b: 2})
const curriedResult = whereEq({a: {b: 2}})({b: 2})
result // $ExpectType boolean
curriedResult // $ExpectType boolean
})
})
```
[](#whereEq)
### without
```typescript
without(matchAgainst: T[], source: T[]): T[]
```
It will return a new array, based on all members of `source` list that are not part of `matchAgainst` list.
`R.equals` is used to determine equality.
Try this R.without example in Rambda REPL
All TypeScript definitions
```typescript
without(matchAgainst: T[], source: T[]): T[];
without(matchAgainst: T[]): (source: T[]) => T[];
```
R.without source
```javascript
import { _indexOf } from './equals.js'
import { reduce } from './reduce.js'
export function without(matchAgainst, source){
if (source === undefined){
return _source => without(matchAgainst, _source)
}
return reduce(
(prev, current) =>
_indexOf(current, matchAgainst) > -1 ? prev : prev.concat(current),
[],
source
)
}
```
Tests
```javascript
import { without as withoutRamda } from 'ramda'
import { without } from './without.js'
test('should return a new list without values in the first argument', () => {
const itemsToOmit = [ 'A', 'B', 'C' ]
const collection = [ 'A', 'B', 'C', 'D', 'E', 'F' ]
expect(without(itemsToOmit, collection)).toEqual([ 'D', 'E', 'F' ])
expect(without(itemsToOmit)(collection)).toEqual([ 'D', 'E', 'F' ])
})
test('with list of objects', () => {
const itemsToOmit = [ { a : 1 }, { c : 3 } ]
const collection = [ { a : 1 }, { b : 2 }, { c : 3 }, { d : 4 } ]
const expected = [ { b : 2 }, { d : 4 } ]
expect(without(itemsToOmit, collection)).toEqual(expected)
expect(withoutRamda(itemsToOmit, collection)).toEqual(expected)
})
test('ramda accepts string as target input while rambda throws', () => {
expect(withoutRamda('0:1', [ '0', '0:1' ])).toEqual([ '0:1' ])
expect(() =>
without('0:1', [ '0', '0:1' ])).toThrowErrorMatchingInlineSnapshot('"Cannot read property \'indexOf\' of 0:1"')
expect(without([ '0:1' ], [ '0', '0:1' ])).toEqual([ '0' ])
})
test('ramda test', () => {
expect(without([ 1, 2 ])([ 1, 2, 1, 3, 4 ])).toEqual([ 3, 4 ])
})
```
TypeScript test
```typescript
import {without} from 'rambda'
const itemsToOmit = ['A', 'B', 'C']
const collection = ['A', 'B', 'C', 'D', 'E', 'F']
describe('R.without', () => {
it('happy', () => {
const result = without(itemsToOmit, collection)
result // $ExpectType string[]
})
it('curried', () => {
const result = without(itemsToOmit)(collection)
result // $ExpectType string[]
})
})
```
[](#without)
### xor
```typescript
xor(x: boolean, y: boolean): boolean
```
Logical XOR
Try this R.xor example in Rambda REPL
All TypeScript definitions
```typescript
xor(x: boolean, y: boolean): boolean;
xor(y: boolean): (y: boolean) => boolean;
```
R.xor source
```javascript
export function xor(a, b){
if (arguments.length === 1) return _b => xor(a, _b)
return Boolean(a) && !b || Boolean(b) && !a
}
```
Tests
```javascript
import { xor } from './xor.js'
test('compares two values with exclusive or', () => {
expect(xor(true, true)).toBeFalse()
expect(xor(true, false)).toBeTrue()
expect(xor(false, true)).toBeTrue()
expect(xor(false, false)).toBeFalse()
})
test('when both values are truthy, it should return false', () => {
expect(xor(true, 'foo')).toBeFalse()
expect(xor(42, true)).toBeFalse()
expect(xor('foo', 42)).toBeFalse()
expect(xor({}, true)).toBeFalse()
expect(xor(true, [])).toBeFalse()
expect(xor([], {})).toBeFalse()
expect(xor(new Date(), true)).toBeFalse()
expect(xor(true, Infinity)).toBeFalse()
expect(xor(Infinity, new Date())).toBeFalse()
})
test('when both values are falsy, it should return false', () => {
expect(xor(null, false)).toBeFalse()
expect(xor(false, undefined)).toBeFalse()
expect(xor(undefined, null)).toBeFalse()
expect(xor(0, false)).toBeFalse()
expect(xor(false, NaN)).toBeFalse()
expect(xor(NaN, 0)).toBeFalse()
expect(xor('', false)).toBeFalse()
})
test('when one argument is truthy and the other is falsy, it should return true', () => {
expect(xor('foo', null)).toBeTrue()
expect(xor(null, 'foo')).toBeTrue()
expect(xor(undefined, 42)).toBeTrue()
expect(xor(42, undefined)).toBeTrue()
expect(xor(Infinity, NaN)).toBeTrue()
expect(xor(NaN, Infinity)).toBeTrue()
expect(xor({}, '')).toBeTrue()
expect(xor('', {})).toBeTrue()
expect(xor(new Date(), 0)).toBeTrue()
expect(xor(0, new Date())).toBeTrue()
expect(xor([], null)).toBeTrue()
expect(xor(undefined, [])).toBeTrue()
})
```
TypeScript test
```typescript
import {xor} from 'rambda'
describe('R.xor', () => {
it('happy', () => {
xor(true, false) // $ExpectType boolean
})
it('curry', () => {
xor(true)(false) // $ExpectType boolean
})
})
```
[](#xor)
### zip
```typescript
zip(x: K[], y: V[]): KeyValuePair[]
```
It will return a new array containing tuples of equally positions items from both `x` and `y` lists.
The returned list will be truncated to match the length of the shortest supplied list.
Try this R.zip example in Rambda REPL
All TypeScript definitions
```typescript
zip(x: K[], y: V[]): KeyValuePair[];
zip(x: K[]): (y: V[]) => KeyValuePair[];
```
R.zip source
```javascript
export function zip(left, right){
if (arguments.length === 1) return _right => zip(left, _right)
const result = []
const length = Math.min(left.length, right.length)
for (let i = 0; i < length; i++){
result[ i ] = [ left[ i ], right[ i ] ]
}
return result
}
```
Tests
```javascript
import { zip } from './zip.js'
const array1 = [ 1, 2, 3 ]
const array2 = [ 'A', 'B', 'C' ]
test('should return an array', () => {
const actual = zip(array1)(array2)
expect(actual).toBeInstanceOf(Array)
})
test('should return and array or tuples', () => {
const expected = [
[ 1, 'A' ],
[ 2, 'B' ],
[ 3, 'C' ],
]
const actual = zip(array1, array2)
expect(actual).toEqual(expected)
})
test('should truncate result to length of shorted input list', () => {
const expectedA = [
[ 1, 'A' ],
[ 2, 'B' ],
]
const actualA = zip([ 1, 2 ], array2)
expect(actualA).toEqual(expectedA)
const expectedB = [
[ 1, 'A' ],
[ 2, 'B' ],
]
const actualB = zip(array1, [ 'A', 'B' ])
expect(actualB).toEqual(expectedB)
})
```
TypeScript test
```typescript
import {zip} from 'rambda'
describe('R.zip', () => {
it('happy', () => {
const array1 = [1, 2, 3]
const array2 = ['A', 'B', 'C']
const result = zip(array1)(array2)
result // $ExpectType KeyValuePair[]
})
})
```
[](#zip)
### zipObj
```typescript
zipObj(keys: K[], values: T[]): { [P in K]: T }
```
It will return a new object with keys of `keys` array and values of `values` array.
Try this R.zipObj example in Rambda REPL
All TypeScript definitions
```typescript
zipObj(keys: K[], values: T[]): { [P in K]: T };
zipObj(keys: K[]): (values: T[]) => { [P in K]: T };
zipObj(keys: K[], values: T[]): { [P in K]: T };
zipObj(keys: K[]): (values: T[]) => { [P in K]: T };
```
R.zipObj source
```javascript
import { take } from './take.js'
export function zipObj(keys, values){
if (arguments.length === 1) return yHolder => zipObj(keys, yHolder)
return take(values.length, keys).reduce((
prev, xInstance, i
) => {
prev[ xInstance ] = values[ i ]
return prev
}, {})
}
```
Tests
```javascript
import { equals } from './equals.js'
import { zipObj } from './zipObj.js'
test('zipObj', () => {
expect(zipObj([ 'a', 'b', 'c' ], [ 1, 2, 3 ])).toEqual({
a : 1,
b : 2,
c : 3,
})
})
test('0', () => {
expect(zipObj([ 'a', 'b' ])([ 1, 2, 3 ])).toEqual({
a : 1,
b : 2,
})
})
test('1', () => {
expect(zipObj([ 'a', 'b', 'c' ])([ 1, 2 ])).toEqual({
a : 1,
b : 2,
})
})
test('ignore extra keys', () => {
const result = zipObj([ 'a', 'b', 'c', 'd', 'e', 'f' ], [ 1, 2, 3 ])
const expected = {
a : 1,
b : 2,
c : 3,
}
expect(equals(result, expected)).toBeTrue()
})
```
TypeScript test
```typescript
import {zipObj} from 'rambda'
describe('R.zipObj', () => {
it('happy', () => {
// this is wrong since 24.10.2020 `@types/ramda` changes
const result = zipObj(['a', 'b', 'c', 'd'], [1, 2, 3])
;[result.a, result.b, result.c, result.d] // $ExpectType number[]
})
it('imported from @types/ramda', () => {
const result = zipObj(['a', 'b', 'c'], [1, 2, 3])
const curriedResult = zipObj(['a', 'b', 'c'])([1, 2, 3])
;[result.a, result.b, result.c] // $ExpectType number[]
;[curriedResult.a, curriedResult.b, curriedResult.c] // $ExpectType number[]
})
})
```
[](#zipObj)
### zipWith
```typescript
zipWith(fn: (x: T, y: U) => TResult, list1: T[], list2: U[]): TResult[]
```
Try this R.zipWith example in Rambda REPL
All TypeScript definitions
```typescript
zipWith(fn: (x: T, y: U) => TResult, list1: T[], list2: U[]): TResult[];
zipWith(fn: (x: T, y: U) => TResult, list1: T[]): (list2: U[]) => TResult[];
zipWith(fn: (x: T, y: U) => TResult): (list1: T[], list2: U[]) => TResult[];
```
R.zipWith source
```javascript
import { curry } from './curry.js'
import { take } from './take.js'
function zipWithFn(
fn, x, y
){
return take(x.length > y.length ? y.length : x.length, x).map((xInstance, i) => fn(xInstance, y[ i ]))
}
export const zipWith = curry(zipWithFn)
```
Tests
```javascript
import { add } from './add.js'
import { zipWith } from './zipWith.js'
const list1 = [ 1, 2, 3 ]
const list2 = [ 10, 20, 30, 40 ]
const list3 = [ 100, 200 ]
test('when second list is shorter', () => {
const result = zipWith(
add, list1, list3
)
expect(result).toEqual([ 101, 202 ])
})
test('when second list is longer', () => {
const result = zipWith(
add, list1, list2
)
expect(result).toEqual([ 11, 22, 33 ])
})
```
TypeScript test
```typescript
import {zipWith} from 'rambda'
const list1 = [1, 2]
const list2 = [10, 20, 30]
describe('R.zipWith', () => {
it('happy', () => {
const result = zipWith(
(x, y) => {
x // $ExpectType number
y // $ExpectType number
return `${x}-${y}`
},
list1,
list2
)
result // $ExpectType string[]
})
it('curried', () => {
const result = zipWith((x, y) => {
x // $ExpectType unknown
y // $ExpectType unknown
return `${x}-${y}`
})(list1, list2)
result // $ExpectType string[]
})
})
```
[](#zipWith)
## ❯ CHANGELOG
9.4.2
- Fix TS issue when `R.take` is used as part of `R.pipe`.
Moving away from `Ramda` types which are problematic in this case:
```typescript
const data = ['foo', 'bar', 'baz', 'qux']
const result = piped(
data,
filter(
x => x.length >= 2
),
takeLast(2),
)
```
9.4.1
- Fix bug with `R.differenceWith` when two arrays has same length - [Issue #750](https://github.com/selfrefactor/rambda/issues/757)
- Allow path input to not be transformed when string numbers are there - [Issue #750](https://github.com/selfrefactor/rambda/issues/750)
9.4.0
- Fix `deno` release
- Fix too strict `true` condition in `R.ifElse` - [Issue #750](https://github.com/selfrefactor/rambda/issues/750)
- Change `R.groupBy` typings to match `@types/ramda` typings
9.3.0
- Breaking change in relation to TS typings of `R.assoc`, `R.dissoc` and `R.modify` - https://github.com/ramda/types/pull/37
- Add `R.isNotEmpty` as it is new method in `Ramda`
- Fix `R.head`/`R.last` TS definition - It returns `undefined` if array has length of 0. Before
9.2.1
- Broken `Deno` build - [Issue #731](https://github.com/selfrefactor/rambda/issues/731)
9.2.0
- `R.once` TS type definition miss to context argument and its type - [Issue #728](https://github.com/selfrefactor/rambda/issues/728)
- Fix implementation of `R.unless` function - https://github.com/selfrefactor/rambda/pull/726
9.1.1
- Faster R.equals with Object.is short circuit - https://github.com/selfrefactor/rambda/pull/725
- Fix R.cond transform is unary - https://github.com/selfrefactor/rambda/issues/720
9.1.0
Add these methods
- insert
- insertAll
- lt
- lte
- isNotNil
- pickBy
- pathSatisfies
- swap
- mergeDeepLeft
9.0.1
- Fix bad TS typings, due to missing declaration - [Issue #716](https://github.com/selfrefactor/rambda/issues/716)
9.0.0
Breaking change in TS definitions of `lenses` as now they are synced to `Ramda` types.
- Add `R.sortWith` - [Issue #707](https://github.com/selfrefactor/rambda/issues/707)
- Add `R.innerJoin`, `R.gt`, `R.gte`, `R.reduceBy`, `R.hasIn`
8.6.0
- Wrong typing for `R.dissocPath` - [Issue #709](https://github.com/selfrefactor/rambda/issues/709)
- Update build dependencies
8.5.0
- 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.
- Wrong `R.partial` TS definition - [Issue #705](https://github.com/selfrefactor/rambda/issues/705)
- Add `R.dropRepeatsBy`
- Add `R.empty`
- Add `R.eqBy`
- Add `R.forEachObjIndexed`
8.4.0
- Add `R.dissocPath`
- Fix TS definitions of `R.head/R.last` and add missing handle of empty string
- Add `R.removeIndex` - method was before only in `Rambdax`, but now since `R.dissocPath` is using it, it is added to main library.
- Allow `R.omit` to pass numbers as part of properties to omit, i.e. `R.omit(['a', 1], {a: {1: 1, 2: 2}})`
- R.keys always returns strings - [MR #700](https://github.com/selfrefactor/rambda/pull/700)
- Improve `R.prepend/R.append` type interference - [MR #699](https://github.com/selfrefactor/rambda/pull/699)
- Change `R.reduce` TS definitions so index is always received - [MR #696](https://github.com/selfrefactor/rambda/pull/696)
- Functions as a type guard in `R.anyPass` TS definitions - [MR #695](https://github.com/selfrefactor/rambda/pull/695)
- Fix R.append's curried type - [MR #694](https://github.com/selfrefactor/rambda/pull/694)
- Fix cannot compare errors in `Deno` with `R.equals` - [Issue #704](https://github.com/selfrefactor/rambda/issues/704).
- Fix cannot compare `BigInt` with `R.equals`
8.3.0
Add the following methods:
- binary
- call
- collectBy
- comparator
- composeWith
8.2.0
Add the following methods:
- addIndex
- addIndexRight
- ap
- aperture
- applyTo
- ascend
- descend
8.1.0
- 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.
- Add `R.differenceWith` method - [Issue #91](https://github.com/selfrefactor/rambdax/issues/91)
8.0.0
- handle falsy values in merge methods - https://github.com/ramda/ramda/pull/3222
- `R.head`/`R.last` don't return `undefined` for non-empty arrays
- `R.type` supports dates in TS definition - `Rambda` already did support dates in JS.
- Improve typings of `R.endsWith/startsWith` with regard to `string` input. - [PR #622](https://github.com/selfrefactor/rambda/pull/622)
- Handle list as falsy value in `R.reduce` - [Ramda MR](https://github.com/ramda/ramda/pull/2997/files)
- `R.nop` is removed - it will be moved to `Rambdax` as `R.noop`
- `R.includes` is no longer using string literal in TypeScript definitions
> Reason for breaking change - synchronize with Ramda `0.29.0` release:
- change order of `R.propEq` - [Ramda MR](https://github.com/ramda/ramda/pull/2938/files)
7.5.0
- 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)
- Add `R.unnest` - [Rambdax issue 89](https://github.com/selfrefactor/rambdax/issues/89)
- `R.uniq` is not using `R.equals` as Ramda does - [Issue #88](https://github.com/selfrefactor/rambdax/issues/88)
- 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)
7.4.0
- Synchronize with `@types/ramda` - `R.prop`, `R.path`, `R.pickAll`
- Remove `esm` Rollup output due to tree-shaking issues.
- Upgrade all dev dependencies.
7.3.0
- Important - changing import declaration in `package.json` in order to fix tree-shaking issue - [Issue #647](https://github.com/selfrefactor/rambda/issues/647)
- Add `R.modify`
- Allow multiple inputs in TypeScript versions of `R.anyPass` and `R.allPass` - [Issue #642](https://github.com/selfrefactor/rambda/issues/604)
- Using wrong clone of object in `R.mergeDeepRight` - [Issue #650](https://github.com/selfrefactor/rambda/issues/650)
- Missing early return in `R.where` - [Issue #648](https://github.com/selfrefactor/rambda/issues/648)
- `R.allPass` doesn't accept more than 1 parameters for function predicates- [Issue #604](https://github.com/selfrefactor/rambda/issues/604)
7.2.1
- Remove bad typings of `R.propIs` which caused the library to cannot be build with TypeScript.
- Drop support for `Wallaby` as per [https://github.com/wallabyjs/public/issues/3037](https://github.com/wallabyjs/public/issues/3037)
7.2.0
- Wrong `R.update` if index is `-1` - [PR #593](https://github.com/selfrefactor/rambda/pull/593)
- Wrong curried typings in `R.anyPass` - [Issue #642](https://github.com/selfrefactor/rambda/issues/642)
- `R.modifyPath` not exported - [Issue #640](https://github.com/selfrefactor/rambda/issues/640)
- Add new method `R.uniqBy`. Implementation is coming from [Ramda MR#2641](https://github.com/ramda/ramda/pull/2641)
- Apply the following changes from `@types/rambda`:
-- [https://github.com/DefinitelyTyped/DefinitelyTyped/commit/bab47272d52fc7bb81e85da36dbe9c905a04d067](add `AnyFunction` and `AnyConstructor`)
-- Improve `R.ifElse` typings - https://github.com/DefinitelyTyped/DefinitelyTyped/pull/59291
-- Make `R.propEq` safe for `null/undefined` arguments - https://github.com/ramda/ramda/pull/2594/files
7.1.4
- `R.mergeRight` not found on `Deno` import - [Issue #633](https://github.com/selfrefactor/rambda/issues/633)
7.1.0
- Add `R.mergeRight` - introduced by Ramda's latest release. While Ramda renames `R.merge`, Rambda will keep `R.merge`.
- 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)
- Replace `Async` with `Promise` as return type of `R.type`.
- Add new types as TypeScript output for `R.type` - "Map", "WeakMap", "Generator", "GeneratorFunction", "BigInt", "ArrayBuffer"
- Add `R.juxt` method
- Add `R.propSatisfies` method
- Add new methods after `Ramda` version upgrade to `0.28.0`:
-- R.count
-- R.modifyPath
-- R.on
-- R.whereAny
-- R.partialObject
7.0.3
Rambda.none has wrong logic introduced in version `7.0.0` - [Issue #625](https://github.com/selfrefactor/rambda/issues/625)
7.0.2
Rambda doesn't work with `pnpm` due to wrong export configuration - [Issue #619](https://github.com/selfrefactor/rambda/issues/619)
7.0.1
- Wrong ESM export configuration in `package.json` - [Issue #614](https://github.com/selfrefactor/rambda/issues/614)
7.0.0
- 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.
Related commit in `@types/ramda` - https://github.com/DefinitelyTyped/DefinitelyTyped/commit/286eff4f76d41eb8f091e7437eabd8a60d97fc1f#diff-4f74803fa83a81e47cb17a7d8a4e46a7e451f4d9e5ce2f1bd7a70a72d91f4bc1
There 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**:
-- R.unless
-- R.toString
-- R.ifElse
-- R.always
-- R.complement
-- R.cond
-- R.is
-- R.sortBy
-- R.dissoc
-- R.toPairs
-- R.assoc
-- R.toLower
-- R.toUpper
- 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`.
- Add `R.apply`, `R.bind` and `R.unapply`
- `R.startsWith/R.endsWith` now support lists as inputs. This way, it matches current Ramda behavior.
- Remove unused typing for `R.chain`.
- `R.map`/`R.filter` no longer accept bad inputs as iterable. This way, Rambda behaves more like Ramda, which also throws.
- Make `R.lastIndexOf` follow the logic of `R.indexOf`.
- Change `R.type` logic to Ramda logic. This way, `R.type` can return `Error` and `Set` as results.
- Add missing logic in `R.equals` to compare sets - [Issue #599](https://github.com/selfrefactor/rambda/issues/599)
- Improve list cloning - [Issue #595](https://github.com/selfrefactor/rambda/issues/595)
- Handle multiple inputs with `R.allPass` and `R.anyPass` - [Issue #604](https://github.com/selfrefactor/rambda/issues/604)
- Fix `R.length` wrong logic with inputs as `{length: 123}` - [Issue #606](https://github.com/selfrefactor/rambda/issues/606).
- Improve non-curry typings of `R.merge` by using types from [mobily/ts-belt](https://github.com/mobily/ts-belt).
- Improve performance of `R.uniqWith`.
- Wrong `R.update` if index is `-1` - [PR #593](https://github.com/selfrefactor/rambda/pull/593)
- Make `R.eqProps` safe for falsy inputs - based on [this opened Ramda PR](https://github.com/ramda/ramda/pull/2943).
- Incorrect benchmarks for `R.pipe/R.compose` - [Issue #608](https://github.com/selfrefactor/rambda/issues/608)
- Fix `R.last/R.head` typings - [Issue #609](https://github.com/selfrefactor/rambda/issues/609)
6.9.0
- Fix slow `R.uniq` methods - [Issue #581](https://github.com/selfrefactor/rambda/issues/581)
Fixing `R.uniq` was done by improving `R.indexOf` which has performance implication to all methods importing `R.indexOf`:
- R.includes
- R.intersection
- R.difference
- R.excludes
- R.symmetricDifference
- R.union
- 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.
6.8.3
- Fix TypeScript build process with `rambda/immutable` - [Issue #572](https://github.com/selfrefactor/rambda/issues/572)
- Add `R.objOf` method
- Add `R.mapObjIndexed` method
- Publish shorter README.md version to NPM
6.8.0
- `R.has` use `Object.prototype.hasOwnProperty`- [Issue #572](https://github.com/selfrefactor/rambda/issues/572)
- Expose `immutable.ts` typings which are Rambda typings with `readonly` statements - [Issue #565](https://github.com/selfrefactor/rambda/issues/565)
- Fix `R.intersection` wrong order compared to Ramda.
- `R.path` wrong return of `null` instead of `undefined` when path value is `null` - [PR #577](https://github.com/selfrefactor/rambda/pull/577)
6.7.0
- Remove `ts-toolbelt` types from TypeScript definitions. Most affected are the following methods, which lose one of its curried definitions:
1. R.maxBy
2. R.minBy
3. R.pathEq
4. R.viewOr
5. R.when
6. R.merge
7. R.mergeDeepRight
8. R.mergeLeft
6.6.0
- Change `R.piped` typings to mimic that of `R.pipe`. Main difference is that `R.pipe` is focused on unary functions.
- Fix wrong logic when `R.without` use `R.includes` while it should use array version of `R.includes`.
- Use uglify plugin for UMD bundle.
- Remove `dist` folder from `.gitignore` in order to fix `Deno` broken package. [Issue #570](https://github.com/selfrefactor/rambda/issues/570)
- Improve `R.fromPairs` typings - [Issue #567](https://github.com/selfrefactor/rambda/issues/567)
6.5.3
- Wrong logic where `R.without` use `R.includes` while it should use the array version of `R.includes`
This is Ramda bug, that Rambda also has before this release - https://github.com/ramda/ramda/issues/3086
6.5.2
- Wrong `R.defaultTo` typings - changes introduced in v6.5.0 are missing their TS equivalent.
- Update dependencies
6.5.1
Fix wrong versions in changelog
6.5.0
- `R.defaultTo` no longer accepts infinite inputs, thus it follows Ramda implementation.
- `R.equals` supports equality of functions.
- `R.pipe` doesn't use `R.compose`.
- Close [Issue #561](https://github.com/selfrefactor/rambda/issues/561) - export several internal TS interfaces and types
- Close [Issue #559](https://github.com/selfrefactor/rambda/issues/559) - improve `R.propOr` typings
- Add `CHANGELOG.md` file in release files list
> This is only part of the changelog. You can read the full text in [CHANGELOG.md](CHANGELOG.md) file.
[](#-changelog)
## ❯ Additional info
> Most influential contributors(in alphabetical order)
-  [@farwayer](https://github.com/farwayer) - improving performance in R.find, R.filter; give the idea how to make benchmarks more reliable;
-  [@thejohnfreeman](https://github.com/thejohnfreeman) - add R.assoc, R.chain;
-  [@peeja](https://github.com/peeja) - add several methods and fix mutiple issues; provides great MR documentation
-  [@helmuthdu](https://github.com/helmuthdu) - add R.clone; help improve code style;
-  [@jpgorman](https://github.com/jpgorman) - add R.zip, R.reject, R.without, R.addIndex;
-  [@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;
-  [@romgrk](https://github.com/romgrk) - add R.groupBy, R.indexBy, R.findLast, R.findLastIndex;
-  [@squidfunk](https://github.com/squidfunk) - add R.assocPath, R.symmetricDifference, R.difference, R.intersperse;
-  [@synthet1c](https://github.com/synthet1c) - add all lenses methods; add R.applySpec, R.converge;
-  [@vlad-zhukov](https://github.com/vlad-zhukov) - help with configuring Rollup, Babel; change export file to use ES module exports;
> Rambda references
- [Interview with Dejan Totef at SurviveJS blog](https://survivejs.com/blog/rambda-interview/)
- [Awesome functional Javascript programming libraries](https://github.com/stoeffel/awesome-fp-js#libraries)
- [Overview of Rambda pros/cons](https://mobily.github.io/ts-belt/docs/#rambda-%EF%B8%8F)
> Links to Rambda
- [awesome-fp-js](https://github.com/stoeffel/awesome-fp-js)
- [Web Tools Weekly #280](https://mailchi.mp/webtoolsweekly/web-tools-280)
- [awesome-docsify](https://github.com/docsifyjs/awesome-docsify)
> Deprecated from `Used by` section
- [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)
[](#-additional-info)
## My other libraries
## Stargazers over time
[](https://starchart.cc/selfrefactor/rambda)