{"id":13482663,"url":"https://github.com/selfrefactor/rambda","last_synced_at":"2025-05-12T13:07:13.776Z","repository":{"id":39898264,"uuid":"79035508","full_name":"selfrefactor/rambda","owner":"selfrefactor","description":"Typescript focused FP library similar to Remeda and Rambda","archived":false,"fork":false,"pushed_at":"2025-05-09T08:30:38.000Z","size":14234,"stargazers_count":1719,"open_issues_count":2,"forks_count":89,"subscribers_count":15,"default_branch":"master","last_synced_at":"2025-05-09T09:30:11.064Z","etag":null,"topics":["fp","functional","functional-programming","functions","lodash","ramda","typescript","utility","utils"],"latest_commit_sha":null,"homepage":"https://selfrefactor.github.io/rambda/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/selfrefactor.png","metadata":{"files":{"readme":".github/README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2017-01-15T13:50:45.000Z","updated_at":"2025-05-08T15:01:15.000Z","dependencies_parsed_at":"2023-10-02T08:02:05.330Z","dependency_job_id":"7bdbfbce-d704-48c3-90ae-a55b80e3fce2","html_url":"https://github.com/selfrefactor/rambda","commit_stats":{"total_commits":2106,"total_committers":62,"mean_commits":33.96774193548387,"dds":"0.23646723646723644","last_synced_commit":"99e3846c3be40afe904257af0713e96fbf4a1eb5"},"previous_names":[],"tags_count":73,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/selfrefactor%2Frambda","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/selfrefactor%2Frambda/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/selfrefactor%2Frambda/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/selfrefactor%2Frambda/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/selfrefactor","download_url":"https://codeload.github.com/selfrefactor/rambda/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253351768,"owners_count":21895027,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fp","functional","functional-programming","functions","lodash","ramda","typescript","utility","utils"],"created_at":"2024-07-31T17:01:04.232Z","updated_at":"2025-05-12T13:07:13.732Z","avatar_url":"https://github.com/selfrefactor.png","language":"JavaScript","readme":"# Rambda\n\n`Rambda` is TypeScript-focused utility library similar to `Remeda` and `Lodash`. \n\nInitially it started as faster alternative to functional programming library `Ramda`, but in order to address many TypeScript issues, now `Rambda` takes a separate path. - [Documentation](https://selfrefactor.github.io/rambda/#/)\n\n![Commit activity](https://img.shields.io/github/commit-activity/y/selfrefactor/rambda)\n![Library size](https://img.shields.io/bundlephobia/minzip/rambda)\n[![install size](https://packagephobia.com/badge?p=rambda)](https://packagephobia.com/result?p=rambda)\n[![PR's Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat)](https://github.com/selfrefactor/rambda/pulls)\n[![GitHub contributors](https://img.shields.io/github/contributors/selfrefactor/rambda.svg)](https://github.com/selfrefactor/rambda/graphs/contributors)\n\n## ❯ Example use\n\n```javascript\nimport { pipe, map, filter } from 'rambda'\n\nconst result = pipe(\n\t[1, 2, 3, 4],\n  filter(x =\u003e x \u003e 2),\n  map(x =\u003e x * 2),\n)\n// =\u003e [6, 8]\n```\n\nYou can test this example in \u003ca href=\"https://rambda.now.sh?const%20result%20%3D%20R.compose(%0A%20%20R.map(x%20%3D%3E%20x%20*%202)%2C%0A%20%20R.filter(x%20%3D%3E%20x%20%3E%202)%0A)(%5B1%2C%202%2C%203%2C%204%5D)%0A%0A%2F%2F%20%3D%3E%20%5B6%2C%208%5D\"\u003eRambda's REPL\u003c/a\u003e\n\n* [API](#api)\n* [Changelog](#-changelog)\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#-example-use)\n\n## ❯ Rambda's features\n\n## ❯ Goals\n\n### Typescript focus\n\nMixing `Functional Programming` and `TypeScript` is not easy.\n\nOne way to solve this is to focus what can be actually achieved and refrain from what is not possible.\n\n### `R.pipe` as the main way to use Rambda\n\n- All methods are meant to be used as part of `R.pipe` chain\n\n- This is the main purpose of functional programming, i.e. to pass data through a chain of functions.\n\n- Having `R.pipe(input, ...fns)` helps TypeScript to infer the types of the input and the output.\n\nHere is one example why `R.pipe` is better than `Ramda.pipe`:\n\n```ts\nconst list = [1, 2, 3];\n\nit('within pipe', () =\u003e {\n\tconst result = pipe(\n\t\tlist,\n\t\tfilter((x) =\u003e {\n\t\t\tx; // $ExpectType number\n\t\t\treturn x \u003e 1;\n\t\t}),\n\t);\n\tresult; // $ExpectType number[]\n});\nit('within Ramda.pipe requires explicit types', () =\u003e {\n\tRamda.pipe(\n\t\t(x) =\u003e x,\n\t\tfilter\u003cnumber\u003e((x) =\u003e {\n\t\t\tx; // $ExpectType number\n\t\t\treturn x \u003e 1;\n\t\t}),\n\t\tfilter((x: number) =\u003e {\n\t\t\tx; // $ExpectType number\n\t\t\treturn x \u003e 1;\n\t\t}),\n\t)(list);\n});\n```\n\n### Keep only the most useful methods\n\nThe idea is to give `TypeScript` users only the most useful methods and let them implement the rest. No magic logic methods that are hard to remember. You shouldn't need to read the documentation to understand what a method does. Its name and signature should be enough.\n\n- Methods that are simply to remember only by its name. Complex logic shouldn't be part of utility library, but part of your codebase.\n\n- Keep only methods which are both useful and which behaviour is obvious from its name. For example, `R.innerJoin` is kept, but `R.identical`, `R.move` is removed. Methods such as `R.toLower`, `R.length` provide little value. Such method are omitted from Rambda on purpose.\n\n- Some generic methods such as `curry` and `assoc` is not easy to be expressed in TypeScript. For this reason `Rambda` omits such methods.\n\n- No `R.cond` or `R.ifElse` as they make the chain less readable.\n\n- No `R.length` as it adds very little value.\n\n- No `R.difference` as user must remember the order of the inputs, i.e. which is compared to and which is compared against.\n\n### One way to use each method\n\nBecause of the focus on `R.pipe`, there is only one way to use each method. This helps with testing and also with TypeScript definitions.\n\n- All methods that 2 inputs, will have to be called with `R.methodName(input1)(input2)`\n- All methods that 3 inputs, will have to be called with `R.methodName(input1, input2)(input3)`\n\n### Immutable TS definitions\n\nYou can use immutable version of Rambda definitions, which is linted with ESLint `functional/prefer-readonly-type` plugin.\n\n```\nimport {filter} from 'rambda/immutable'\n```\n\n### Deno support \n\n```\nimport * as R from \"https://deno.land/x/rambda/mod.ts\";\n\nR.filter(x =\u003e x \u003e 1)([1, 2, 3])\n```\n\n### Dot notation for `R.path`\n\nStandard usage of `R.path` is `R.path(['a', 'b'])({a: {b: 1} })`.\n\nIn **Rambda** you have the choice to use dot notation(which is arguably more readable):\n\n```\nR.path('a.b')({a: {b: 1} })\n```\n\nPlease note that since path input is turned into array, i.e. if you want `R.path(['a','1', 'b'])({a: {'1': {b: 2}}})` to return `2`, you will have to pass array path, not string path. If you pass `a.1.b`, it will turn path input to `['a', 1, 'b']`.\n\n### Comma notation for `R.pick` and `R.omit`\n\nSimilar to dot notation, but the separator is comma(`,`) instead of dot(`.`).\n\n```\nR.pick('a,b', {a: 1 , b: 2, c: 3} })\n// No space allowed between properties\n```\n\n### Fast performance compared to Ramda\n\nSince `Rambda` methods doesn't use so many internals, it is faster than `Ramda`.\nPrior to version `10`, benchmark summary was included, but now the main selling point is the TypeScript focus, not performance so this is no longer included.\n\n### Differences between Rambda and Ramda\n\nUp until version `9.4.2`, the aim of Rambda was to match as much as possible the Ramda API.\n\nDocumentation site of `Rambda` version `9.4.2` is available [here](https://selfrefactor.github.io/rambda-v9/).\n\nFrom version `10.0.0` onwards, Rambda will start to diverge from Ramda in order to address some of the issues that Ramda has.\n\n\u003cdetails\u003e\n\u003csummary\u003e\n\tRamda issues\n\u003c/summary\u003e\n\n-- Typescript support - this is the main reason for the divergence. Most of design decisions in Rambda are made with Typescript in mind.\n\n-- Methods that imply side-effect, which is not FP oriented, e.g. `R.forEach`.\n\n-- Naming of methods that doesn't match developer's expectation, such as `R.chain`, which should be called `flatMap`.\n\n-- Naming of methods is sometimes too generic to be remembered such as `R.update`, `R.modify`, `R.where`.\n\n-- Methods that are already present in standard JavaScript, such as `R.toLower`, `R.length`.\n\n-- `R.compose` doesn't have the best possible TypeScript support.\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#-rambdas-features)\n\n## API\n\n### addProp\n\n```typescript\n\naddProp\u003cT extends object, P extends PropertyKey, V extends unknown\u003e(\n\tprop: P,\n\tvalue: V\n): (obj: T) =\u003e MergeTypes\u003cT \u0026 Record\u003cP, V\u003e\u003e\n```\n\nIt adds new key-value pair to the object.\n\n```javascript\nconst result = R.pipe(\n\t{ a: 1, b: 'foo' }, \n\tR.addProp('c', 3)\n)\n// =\u003e { a: 1, b: 'foo', c: 3 }\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20result%20%3D%20R.pipe(%0A%09%7B%20a%3A%201%2C%20b%3A%20'foo'%20%7D%2C%20%0A%09R.addProp('c'%2C%203)%0A)%0A%2F%2F%20%3D%3E%20%7B%20a%3A%201%2C%20b%3A%20'foo'%2C%20c%3A%203%20%7D\"\u003eTry this \u003cstrong\u003eR.addProp\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\naddProp\u003cT extends object, P extends PropertyKey, V extends unknown\u003e(\n\tprop: P,\n\tvalue: V\n): (obj: T) =\u003e MergeTypes\u003cT \u0026 Record\u003cP, V\u003e\u003e;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.addProp\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function addProp(key, value) {\n  return obj =\u003e ({ ...obj, [key]: value })\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { addProp } from \"./addProp.js\"\n\ntest('happy', () =\u003e {\n\tconst result = addProp('a', 1)({ b: 2 })\n\tconst expected = { a: 1, b: 2 }\n\n\texpect(result).toEqual(expected)\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { addProp, pipe } from 'rambda'\n\nit('R.addProp', () =\u003e {\n\tconst result = pipe({ a: 1, b: 'foo' }, addProp('c', 3))\n\tresult.a // $ExpectType number\n\tresult.b // $ExpectType string\n\tresult.c // $ExpectType number\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#addProp)\n\n### all\n\n```typescript\n\nall\u003cT\u003e(predicate: (x: T) =\u003e boolean): (list: T[]) =\u003e boolean\n```\n\nIt returns `true`, if all members of array `list` returns `true`, when applied as argument to `predicate` function.\n\n```javascript\nconst list = [ 0, 1, 2, 3, 4 ]\nconst predicate = x =\u003e x \u003e -1\n\nconst result = R.pipe(\n\tlist,\n\tR.all(predicate)\n) // =\u003e true\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20list%20%3D%20%5B%200%2C%201%2C%202%2C%203%2C%204%20%5D%0Aconst%20predicate%20%3D%20x%20%3D%3E%20x%20%3E%20-1%0A%0Aconst%20result%20%3D%20R.pipe(%0A%09list%2C%0A%09R.all(predicate)%0A)%20%2F%2F%20%3D%3E%20true\"\u003eTry this \u003cstrong\u003eR.all\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nall\u003cT\u003e(predicate: (x: T) =\u003e boolean): (list: T[]) =\u003e boolean;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.all\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function all(predicate) {\n  return list =\u003e {\n    for (let i = 0; i \u003c list.length; i++) {\n      if (!predicate(list[i])) {\n        return false\n      }\n    }\n\n    return true\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { all } from './all.js'\n\nconst list = [0, 1, 2, 3, 4]\n\ntest('when true', () =\u003e {\n  const fn = x =\u003e x \u003e -1\n\n  expect(all(fn)(list)).toBeTruthy()\n})\n\ntest('when false', () =\u003e {\n  const fn = x =\u003e x \u003e 2\n\n  expect(all(fn)(list)).toBeFalsy()\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport * as R from 'rambda'\n\ndescribe('all', () =\u003e {\n  it('happy', () =\u003e {\n    const result = R.pipe(\n      [1, 2, 3],\n      R.all(x =\u003e {\n        x // $ExpectType number\n        return x \u003e 0\n      }),\n    )\n    result // $ExpectType boolean\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#all)\n\n### allPass\n\n```typescript\n\nallPass\u003cF extends (...args: any[]) =\u003e boolean\u003e(predicates: readonly F[]): F\n```\n\nIt returns `true`, if all functions of `predicates` return `true`, when `input` is their argument.\n\n```javascript\nconst list = [[1, 2, 3, 4], [3, 4, 5]]\nconst result = R.pipe(\n\tlist,\n\tR.filter(R.allPass([R.includes(2), R.includes(3)]))\n) // =\u003e [[1, 2, 3, 4]]\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20list%20%3D%20%5B%5B1%2C%202%2C%203%2C%204%5D%2C%20%5B3%2C%204%2C%205%5D%5D%0Aconst%20result%20%3D%20R.pipe(%0A%09list%2C%0A%09R.filter(R.allPass(%5BR.includes(2)%2C%20R.includes(3)%5D))%0A)%20%2F%2F%20%3D%3E%20%5B%5B1%2C%202%2C%203%2C%204%5D%5D\"\u003eTry this \u003cstrong\u003eR.allPass\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nallPass\u003cF extends (...args: any[]) =\u003e boolean\u003e(predicates: readonly F[]): F;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.allPass\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function allPass(predicates) {\n  return input =\u003e {\n    let counter = 0\n    while (counter \u003c predicates.length) {\n      if (!predicates[counter](input)) {\n        return false\n      }\n      counter++\n    }\n\n    return true\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { allPass } from './allPass.js'\nimport { filter } from './filter.js'\nimport { includes } from './includes.js'\nimport { pipe } from './pipe.js'\n\nconst list = [\n  [1, 2, 3, 4],\n  [3, 4, 5],\n]\ntest('happy', () =\u003e {\n  const result = pipe(list, filter(allPass([includes(2), includes(3)])))\n  expect(result).toEqual([[1, 2, 3, 4]])\n})\n\ntest('when returns false', () =\u003e {\n  const result = pipe(list, filter(allPass([includes(12), includes(31)])))\n  expect(result).toEqual([])\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport * as R from 'rambda'\n\ndescribe('allPass', () =\u003e {\n  it('happy', () =\u003e {\n    const list = [\n      [1, 2, 3, 4],\n      [3, 4, 5],\n    ]\n    const result = R.pipe(list, R.map(R.allPass([R.includes(3), R.includes(4)])))\n    result // $ExpectType boolean[]\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#allPass)\n\n### any\n\n```typescript\n\nany\u003cT\u003e(predicate: (x: T) =\u003e boolean): (list: T[]) =\u003e boolean\n```\n\nIt returns `true`, if at least one member of `list` returns true, when passed to a `predicate` function.\n\n```javascript\nconst list = [1, 2, 3]\nconst predicate = x =\u003e x * x \u003e 8\nR.any(fn)(list)\n// =\u003e true\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20list%20%3D%20%5B1%2C%202%2C%203%5D%0Aconst%20predicate%20%3D%20x%20%3D%3E%20x%20*%20x%20%3E%208%0Aconst%20result%20%3D%20R.any(fn)(list)%0A%2F%2F%20%3D%3E%20true\"\u003eTry this \u003cstrong\u003eR.any\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nany\u003cT\u003e(predicate: (x: T) =\u003e boolean): (list: T[]) =\u003e boolean;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.any\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function any(predicate) {\n  return list =\u003e {\n    let counter = 0\n    while (counter \u003c list.length) {\n      if (predicate(list[counter], counter)) {\n        return true\n      }\n      counter++\n    }\n\n    return false\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { any } from './any.js'\n\nconst list = [1, 2, 3]\n\ntest('happy', () =\u003e {\n  expect(any(x =\u003e x \u003e 2)(list)).toBeTruthy()\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { any, pipe } from 'rambda'\n\nit('R.any', () =\u003e {\n  const result = pipe(\n    [1, 2, 3],\n    any(x =\u003e {\n      x // $ExpectType number\n      return x \u003e 2\n    }),\n  )\n  result // $ExpectType boolean\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#any)\n\n### anyPass\n\n```typescript\n\nanyPass\u003cT, TF1 extends T, TF2 extends T\u003e(\n  predicates: [(a: T) =\u003e a is TF1, (a: T) =\u003e a is TF2],\n): (a: T) =\u003e a is TF1 | TF2\n```\n\nIt accepts list of `predicates` and returns a function. This function with its `input` will return `true`, if any of `predicates` returns `true` for this `input`.\n\n\u003e :boom: Function accepts only one input, but in Ramda it accepts indefinite number of arguments.\n\n```javascript\nconst isBig = x =\u003e x \u003e 20\nconst isOdd = x =\u003e x % 2 === 1\nconst input = 11\n\nconst fn = R.anyPass(\n  [isBig, isOdd]\n)\n\nconst result = fn(input) \n// =\u003e true\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20isBig%20%3D%20x%20%3D%3E%20x%20%3E%2020%0Aconst%20isOdd%20%3D%20x%20%3D%3E%20x%20%25%202%20%3D%3D%3D%201%0Aconst%20input%20%3D%2011%0A%0Aconst%20fn%20%3D%20R.anyPass(%0A%20%20%5BisBig%2C%20isOdd%5D%0A)%0A%0Aconst%20result%20%3D%20fn(input)%20%0A%2F%2F%20%3D%3E%20true\"\u003eTry this \u003cstrong\u003eR.anyPass\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nanyPass\u003cT, TF1 extends T, TF2 extends T\u003e(\n  predicates: [(a: T) =\u003e a is TF1, (a: T) =\u003e a is TF2],\n): (a: T) =\u003e a is TF1 | TF2;\nanyPass\u003cT, TF1 extends T, TF2 extends T, TF3 extends T\u003e(\n  predicates: [(a: T) =\u003e a is TF1, (a: T) =\u003e a is TF2, (a: T) =\u003e a is TF3],\n): (a: T) =\u003e a is TF1 | TF2 | TF3;\nanyPass\u003cT, TF1 extends T, TF2 extends T, TF3 extends T\u003e(\n  predicates: [(a: T) =\u003e a is TF1, (a: T) =\u003e a is TF2, (a: T) =\u003e a is TF3],\n): (a: T) =\u003e a is TF1 | TF2 | TF3;\nanyPass\u003cT, TF1 extends T, TF2 extends T, TF3 extends T, TF4 extends T\u003e(\n  predicates: [(a: T) =\u003e a is TF1, (a: T) =\u003e a is TF2, (a: T) =\u003e a is TF3, (a: T) =\u003e a is TF4],\n): (a: T) =\u003e a is TF1 | TF2 | TF3 | TF4;\nanyPass\u003cT, TF1 extends T, TF2 extends T, TF3 extends T, TF4 extends T, TF5 extends T\u003e(\n  predicates: [\n    (a: T) =\u003e a is TF1,\n    (a: T) =\u003e a is TF2,\n    (a: T) =\u003e a is TF3,\n    (a: T) =\u003e a is TF4,\n    (a: T) =\u003e a is TF5\n  ],\n): (a: T) =\u003e a is TF1 | TF2 | TF3 | TF4 | TF5;\nanyPass\u003cT, TF1 extends T, TF2 extends T, TF3 extends T, TF4 extends T, TF5 extends T, TF6 extends T\u003e(\n  predicates: [\n    (a: T) =\u003e a is TF1,\n    (a: T) =\u003e a is TF2,\n    (a: T) =\u003e a is TF3,\n    (a: T) =\u003e a is TF4,\n    (a: T) =\u003e a is TF5,\n    (a: T) =\u003e a is TF6\n  ],\n): (a: T) =\u003e a is TF1 | TF2 | TF3 | TF4 | TF5 | TF6;\nanyPass\u003cF extends (...args: any[]) =\u003e boolean\u003e(predicates: readonly F[]): F;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.anyPass\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function anyPass(predicates) {\n  return input =\u003e {\n    let counter = 0\n    while (counter \u003c predicates.length) {\n      if (predicates[counter](input)) {\n        return true\n      }\n      counter++\n    }\n\n    return false\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { anyPass } from './anyPass.js'\n\ntest('happy', () =\u003e {\n  const rules = [x =\u003e typeof x === 'string', x =\u003e x \u003e 10]\n  const predicate = anyPass(rules)\n  expect(predicate('foo')).toBeTruthy()\n  expect(predicate(6)).toBeFalsy()\n})\n\ntest('happy', () =\u003e {\n  const rules = [x =\u003e typeof x === 'string', x =\u003e x \u003e 10]\n\n  expect(anyPass(rules)(11)).toBeTruthy()\n  expect(anyPass(rules)(undefined)).toBeFalsy()\n})\n\nconst obj = {\n  a: 1,\n  b: 2,\n}\n\ntest('when returns true', () =\u003e {\n  const conditionArr = [val =\u003e val.a === 1, val =\u003e val.a === 2]\n\n  expect(anyPass(conditionArr)(obj)).toBeTruthy()\n})\n\ntest('when returns false', () =\u003e {\n  const conditionArr = [val =\u003e val.a === 2, val =\u003e val.b === 3]\n\n  expect(anyPass(conditionArr)(obj)).toBeFalsy()\n})\n\ntest('with empty predicates list', () =\u003e {\n  expect(anyPass([])(3)).toBeFalsy()\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { anyPass, filter } from 'rambda'\n\ndescribe('anyPass', () =\u003e {\n  it('issue #604', () =\u003e {\n    const plusEq = (w: number, x: number, y: number, z: number) =\u003e w + x === y + z\n    const result = anyPass([plusEq])(3, 3, 3, 3)\n\n    result // $ExpectType boolean\n  })\n  it('issue #642', () =\u003e {\n    const isGreater = (num: number) =\u003e num \u003e 5\n    const pred = anyPass([isGreater])\n    const xs = [0, 1, 2, 3]\n\n    const filtered1 = filter(pred)(xs)\n    filtered1 // $ExpectType number[]\n    const filtered2 = xs.filter(pred)\n    filtered2 // $ExpectType number[]\n  })\n  it('functions as a type guard', () =\u003e {\n    const isString = (x: unknown): x is string =\u003e typeof x === 'string'\n    const isNumber = (x: unknown): x is number =\u003e typeof x === 'number'\n    const isBoolean = (x: unknown): x is boolean =\u003e typeof x === 'boolean'\n\n    const isStringNumberOrBoolean = anyPass([isString, isNumber, isBoolean])\n\n    const aValue: unknown = 1\n\n    if (isStringNumberOrBoolean(aValue)) {\n      aValue // $ExpectType string | number | boolean\n    }\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#anyPass)\n\n### append\n\n```typescript\n\nappend\u003cT\u003e(el: T): (list: T[]) =\u003e T[]\n```\n\nIt adds element `x` at the end of `iterable`.\n\n```javascript\nconst x = 'foo'\n\nconst result = R.append(x, ['bar', 'baz'])\n// =\u003e ['bar', 'baz', 'foo']\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20x%20%3D%20'foo'%0A%0Aconst%20result%20%3D%20R.append(x%2C%20%5B'bar'%2C%20'baz'%5D)%0A%2F%2F%20%3D%3E%20%5B'bar'%2C%20'baz'%2C%20'foo'%5D\"\u003eTry this \u003cstrong\u003eR.append\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nappend\u003cT\u003e(el: T): (list: T[]) =\u003e T[];\nappend\u003cT\u003e(el: T): (list: readonly T[]) =\u003e T[];\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.append\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nimport { cloneList } from './_internals/cloneList.js'\n\nexport function append(x) {\n  return list =\u003e {\n    const clone = cloneList(list)\n    clone.push(x)\n\n    return clone\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { append } from './append.js'\n\ntest('happy', () =\u003e {\n  expect(append('tests')(['write', 'more'])).toEqual(['write', 'more', 'tests'])\n})\n\ntest('append to empty array', () =\u003e {\n  expect(append('tests')([])).toEqual(['tests'])\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { append, pipe, prepend } from 'rambda'\n\nconst listOfNumbers = [1, 2, 3]\n\ndescribe('R.append/R.prepend', () =\u003e {\n  it('happy', () =\u003e {\n    const result = pipe(listOfNumbers, append(4), prepend(0))\n    result // $ExpectType number[]\n  })\n  it('with object', () =\u003e {\n    const result = pipe([{ a: 1 }], append({ a: 10 }), prepend({ a: 20 }))\n    result // $ExpectType { a: number; }[]\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#append)\n\n### ascend\n\nHelper function to be used with `R.sort` to sort list in ascending order.\n\n```javascript\nconst result = R.pipe(\n\t[{a: 1}, {a: 2}, {a: 0}],\n\tR.sort(R.ascend(R.prop('a')))\n)\n// =\u003e [{a: 0}, {a: 1}, {a: 2}]\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20result%20%3D%20R.pipe(%0A%09%5B%7Ba%3A%201%7D%2C%20%7Ba%3A%202%7D%2C%20%7Ba%3A%200%7D%5D%2C%0A%09R.sort(R.ascend(R.prop('a')))%0A)%0A%2F%2F%20%3D%3E%20%5B%7Ba%3A%200%7D%2C%20%7Ba%3A%201%7D%2C%20%7Ba%3A%202%7D%5D\"\u003eTry this \u003cstrong\u003eR.ascend\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#ascend)\n\n### checkObjectWithSpec\n\n```typescript\n\ncheckObjectWithSpec\u003cT\u003e(spec: T): \u003cU\u003e(testObj: U) =\u003e boolean\n```\n\nIt returns `true` if all each property in `conditions` returns `true` when applied to corresponding property in `input` object.\n\n```javascript\nconst condition = R.checkObjectWithSpec({\n  a : x =\u003e typeof x === \"string\",\n  b : x =\u003e x === 4\n})\nconst input = {\n  a : \"foo\",\n  b : 4,\n  c : 11,\n}\n\nconst result = condition(input) \n// =\u003e true\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20condition%20%3D%20R.checkObjectWithSpec(%7B%0A%20%20a%20%3A%20x%20%3D%3E%20typeof%20x%20%3D%3D%3D%20%22string%22%2C%0A%20%20b%20%3A%20x%20%3D%3E%20x%20%3D%3D%3D%204%0A%7D)%0Aconst%20input%20%3D%20%7B%0A%20%20a%20%3A%20%22foo%22%2C%0A%20%20b%20%3A%204%2C%0A%20%20c%20%3A%2011%2C%0A%7D%0A%0Aconst%20result%20%3D%20condition(input)%20%0A%2F%2F%20%3D%3E%20true\"\u003eTry this \u003cstrong\u003eR.checkObjectWithSpec\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\ncheckObjectWithSpec\u003cT\u003e(spec: T): \u003cU\u003e(testObj: U) =\u003e boolean;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.checkObjectWithSpec\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function checkObjectWithSpec(conditions) {\n  return input =\u003e {\n    let shouldProceed = true\n    for (const prop in conditions) {\n      if (!shouldProceed) {\n        continue\n      }\n      const result = conditions[prop](input[prop])\n      if (shouldProceed \u0026\u0026 result === false) {\n        shouldProceed = false\n      }\n    }\n\n    return shouldProceed\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { checkObjectWithSpec } from './checkObjectWithSpec.js'\nimport { equals } from './equals.js'\n\ntest('when true', () =\u003e {\n  const result = checkObjectWithSpec({\n    a: equals('foo'),\n    b: equals('bar'),\n  })({\n    a: 'foo',\n    b: 'bar',\n    x: 11,\n    y: 19,\n  })\n\n  expect(result).toBeTruthy()\n})\n\ntest('when false | early exit', () =\u003e {\n  let counter = 0\n  const equalsFn = expected =\u003e input =\u003e {\n    counter++\n\n    return input === expected\n  }\n  const predicate = checkObjectWithSpec({\n    a: equalsFn('foo'),\n    b: equalsFn('baz'),\n  })\n  expect(\n    predicate({\n      a: 'notfoo',\n      b: 'notbar',\n    }),\n  ).toBeFalsy()\n  expect(counter).toBe(1)\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { checkObjectWithSpec, equals } from 'rambda'\n\ndescribe('R.checkObjectWithSpec', () =\u003e {\n  it('happy', () =\u003e {\n    const input = {\n      a: 'foo',\n      b: 'bar',\n      x: 11,\n      y: 19,\n    }\n    const conditions = {\n      a: equals('foo'),\n      b: equals('bar'),\n    }\n    const result = checkObjectWithSpec(conditions)(input)\n    result // $ExpectType boolean\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#checkObjectWithSpec)\n\n### compact\n\n```typescript\n\ncompact\u003cT\u003e(list: T[]): Array\u003cStrictNonNullable\u003cT\u003e\u003e\n```\n\nIt removes `null` and `undefined` members from list or object input.\n\n```javascript\nconst result = R.pipe(\n\t{\n\t\ta: [ undefined, '', 'a', 'b', 'c'],\n\t\tb: [1,2, null, 0, undefined, 3],\n\t\tc: { a: 1, b: 2, c: 0, d: undefined, e: null, f: false },\n\t},\n\tx =\u003e ({\n\t\ta: R.compact(x.a),\n\t\tb: R.compact(x.b),\n\t\tc: R.compact(x.c)\n\t})\n)\n// =\u003e { a: ['a', 'b', 'c'], b: [1, 2, 3], c: { a: 1, b: 2, c: 0, f: false } }\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20result%20%3D%20R.pipe(%0A%09%7B%0A%09%09a%3A%20%5B%20undefined%2C%20''%2C%20'a'%2C%20'b'%2C%20'c'%5D%2C%0A%09%09b%3A%20%5B1%2C2%2C%20null%2C%200%2C%20undefined%2C%203%5D%2C%0A%09%09c%3A%20%7B%20a%3A%201%2C%20b%3A%202%2C%20c%3A%200%2C%20d%3A%20undefined%2C%20e%3A%20null%2C%20f%3A%20false%20%7D%2C%0A%09%7D%2C%0A%09x%20%3D%3E%20(%7B%0A%09%09a%3A%20R.compact(x.a)%2C%0A%09%09b%3A%20R.compact(x.b)%2C%0A%09%09c%3A%20R.compact(x.c)%0A%09%7D)%0A)%0A%2F%2F%20%3D%3E%20%7B%20a%3A%20%5B'a'%2C%20'b'%2C%20'c'%5D%2C%20b%3A%20%5B1%2C%202%2C%203%5D%2C%20c%3A%20%7B%20a%3A%201%2C%20b%3A%202%2C%20c%3A%200%2C%20f%3A%20false%20%7D%20%7D\"\u003eTry this \u003cstrong\u003eR.compact\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\ncompact\u003cT\u003e(list: T[]): Array\u003cStrictNonNullable\u003cT\u003e\u003e;\ncompact\u003cT extends object\u003e(record: T): {\n  [K in keyof T as Exclude\u003cT[K], null | undefined\u003e extends never\n    ? never\n    : K\n  ]: Exclude\u003cT[K], null | undefined\u003e\n};\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.compact\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nimport { isArray } from './_internals/isArray.js'\nimport { reject } from './reject.js'\nimport { rejectObject } from './rejectObject.js'\n\nconst isNullOrUndefined = x =\u003e x === null || x === undefined\n\nexport function compact(input){\n\tif(isArray(input)){\n\t\treturn reject(isNullOrUndefined)(input)\n\t}\n\treturn rejectObject(isNullOrUndefined)(input)\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { compact } from './compact.js'\nimport { pipe } from './pipe.js'\n\ntest('happy', () =\u003e {\n  const result = pipe(\n\t\t{\n\t\t\ta: [ undefined, 'a', 'b', 'c'],\n\t\t\tb: [1,2, null, 0, undefined, 3],\n\t\t\tc: { a: 1, b: 2, c: 0, d: undefined, e: null, f: false },\n\t\t},\n\t\tx =\u003e ({\n\t\t\ta: compact(x.a),\n\t\t\tb: compact(x.b),\n\t\t\tc: compact(x.c)\n\t\t})\n\t)\n\texpect(result.a).toEqual(['a', 'b', 'c'])\n\texpect(result.b).toEqual([1,2,0,3])\n\texpect(result.c).toEqual({ a: 1, b: 2,c:0, f: false })\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { compact, pipe } from 'rambda'\n\nit('R.compact', () =\u003e {\n\t\tlet result = pipe(\n\t\t\t{\n\t\t\t\ta: [ undefined, '', 'a', 'b', 'c', null ],\n\t\t\t\tb: [1,2, null, 0, undefined, 3],\n\t\t\t\tc: { a: 1, b: 2, c: 0, d: undefined, e: null, f: false },\n\t\t\t},\n\t\t\tx =\u003e ({\n\t\t\t\ta: compact(x.a),\n\t\t\t\tb: compact(x.b),\n\t\t\t\tc: compact(x.c)\n\t\t\t})\n\t\t)\n\n\t\tresult.a // $ExpectType string[]\n\t\tresult.b // $ExpectType number[]\n\t\tresult.c // $ExpectType { a: number; b: number; c: number; f: boolean; }\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#compact)\n\n### complement\n\nIt returns `inverted` version of `origin` function that accept `input` as argument.\n\nThe return value of `inverted` is the negative boolean value of `origin(input)`.\n\n```javascript\nconst fn = x =\u003e x \u003e 5\nconst inverted = complement(fn)\n\nconst result = [\n  fn(7),\n  inverted(7)\n] =\u003e [ true, false ]\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20fn%20%3D%20x%20%3D%3E%20x%20%3E%205%0Aconst%20inverted%20%3D%20complement(fn)%0A%0Aconst%20result%20%3D%20%5B%0A%20%20fn(7)%2C%0A%20%20inverted(7)%0A%5D%20%3D%3E%20%5B%20true%2C%20false%20%5D\"\u003eTry this \u003cstrong\u003eR.complement\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#complement)\n\n### concat\n\nIt returns a new string or array, which is the result of merging `x` and `y`.\n\n```javascript\nR.concat([1, 2])([3, 4]) // =\u003e [1, 2, 3, 4]\nR.concat('foo')('bar') // =\u003e 'foobar'\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?R.concat(%5B1%2C%202%5D)(%5B3%2C%204%5D)%20%2F%2F%20%3D%3E%20%5B1%2C%202%2C%203%2C%204%5D%0Aconst%20result%20%3D%20R.concat('foo')('bar')%20%2F%2F%20%3D%3E%20'foobar'\"\u003eTry this \u003cstrong\u003eR.concat\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#concat)\n\n### count\n\nIt counts how many times `predicate` function returns `true`, when supplied with iteration of `list`.\n\n```javascript\nconst list = [{a: 1}, 1, {a:2}]\nconst result = R.count(x =\u003e x.a !== undefined)(list)\n// =\u003e 2\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20list%20%3D%20%5B%7Ba%3A%201%7D%2C%201%2C%20%7Ba%3A2%7D%5D%0Aconst%20result%20%3D%20R.count(x%20%3D%3E%20x.a%20!%3D%3D%20undefined)(list)%0A%2F%2F%20%3D%3E%202\"\u003eTry this \u003cstrong\u003eR.count\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#count)\n\n### countBy\n\n```typescript\n\ncountBy\u003cT\u003e(fn: (x: T) =\u003e string | number): (list: T[]) =\u003e { [index: string]: number }\n```\n\nIt counts elements in a list after each instance of the input list is passed through `transformFn` function.\n\n```javascript\nconst list = [ 'a', 'A', 'b', 'B', 'c', 'C' ]\n\nconst result = countBy(x =\u003e x.toLowerCase())( list)\nconst expected = { a: 2, b: 2, c: 2 }\n// =\u003e `result` is equal to `expected`\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20list%20%3D%20%5B%20'a'%2C%20'A'%2C%20'b'%2C%20'B'%2C%20'c'%2C%20'C'%20%5D%0A%0Aconst%20result%20%3D%20countBy(x%20%3D%3E%20x.toLowerCase())(%20list)%0Aconst%20expected%20%3D%20%7B%20a%3A%202%2C%20b%3A%202%2C%20c%3A%202%20%7D%0A%2F%2F%20%3D%3E%20%60result%60%20is%20equal%20to%20%60expected%60\"\u003eTry this \u003cstrong\u003eR.countBy\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\ncountBy\u003cT\u003e(fn: (x: T) =\u003e string | number): (list: T[]) =\u003e { [index: string]: number };\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.countBy\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function countBy(fn) {\n  return list =\u003e {\n    const willReturn = {}\n\n    list.forEach(item =\u003e {\n      const key = fn(item)\n      if (!willReturn[key]) {\n        willReturn[key] = 1\n      } else {\n        willReturn[key]++\n      }\n    })\n\n    return willReturn\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { countBy } from './countBy.js'\n\nconst list = ['a', 'A', 'b', 'B', 'c', 'C']\n\ntest('happy', () =\u003e {\n  const result = countBy(x =\u003e x.toLowerCase())(list)\n  expect(result).toEqual({\n    a: 2,\n    b: 2,\n    c: 2,\n  })\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { countBy, pipe } from 'rambda'\n\nconst list = ['a', 'A', 'b', 'B', 'c', 'C']\n\nit('R.countBy', () =\u003e {\n  const result = pipe(\n    list,\n    countBy(x =\u003e x.toLowerCase()),\n  )\n  result.a // $ExpectType number\n  result.foo // $ExpectType number\n  result // $ExpectType { [index: string]: number; }\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#countBy)\n\n### createObjectFromKeys\n\n```typescript\n\ncreateObjectFromKeys\u003cconst K extends readonly PropertyKey[], V\u003e(\n\tfn: (key: K[number]) =\u003e V\n): (keys: K) =\u003e { [P in K[number]]: V }\n```\n\n```javascript\nconst result = R.createObjectFromKeys(\n\t(x, index) =\u003e `${x}-${index}`\n)(['a', 'b', 'c'])\n// =\u003e {a: 'a-0', b: 'b-1', c: 'c-2'}\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20result%20%3D%20R.createObjectFromKeys(%0A%09(x%2C%20index)%20%3D%3E%20%60%24%7Bx%7D-%24%7Bindex%7D%60%0A)(%5B'a'%2C%20'b'%2C%20'c'%5D)%0A%2F%2F%20%3D%3E%20%7Ba%3A%20'a-0'%2C%20b%3A%20'b-1'%2C%20c%3A%20'c-2'%7D\"\u003eTry this \u003cstrong\u003eR.createObjectFromKeys\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\ncreateObjectFromKeys\u003cconst K extends readonly PropertyKey[], V\u003e(\n\tfn: (key: K[number]) =\u003e V\n): (keys: K) =\u003e { [P in K[number]]: V };\ncreateObjectFromKeys\u003cconst K extends readonly PropertyKey[], V\u003e(\n\tfn: (key: K[number], index: number) =\u003e V\n): (keys: K) =\u003e { [P in K[number]]: V };\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.createObjectFromKeys\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function createObjectFromKeys(keys) {\n\treturn fn =\u003e {\n\t\tconst result = {}\n\t\tkeys.forEach((key, index) =\u003e {\n\t\t\tresult[key] = fn(key, index)\n\t\t})\n\n\t\treturn result\n\t}\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { createObjectFromKeys } from './createObjectFromKeys.js'\n\ntest('happy', () =\u003e {\n\tconst result = createObjectFromKeys(['a', 'b'])((key, index) =\u003e key.toUpperCase() + index)\n\tconst expected = { a: 'A0', b: 'B1' }\n\n\texpect(result).toEqual(expected)\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#createObjectFromKeys)\n\n### defaultTo\n\n```typescript\n\ndefaultTo\u003cT\u003e(defaultValue: T): (input: unknown) =\u003e T\n```\n\nIt returns `defaultValue`, if all of `inputArguments` are `undefined`, `null` or `NaN`.\n\nElse, it returns the first truthy `inputArguments` instance(from left to right).\n\n\u003e :boom: Typescript Note: Pass explicit type annotation when used with **R.pipe/R.compose** for better type inference\n\n```javascript\nR.defaultTo('foo')('bar') // =\u003e 'bar'\nR.defaultTo('foo'))(undefined) // =\u003e 'foo'\n\n// Important - emtpy string is not falsy value\nR.defaultTo('foo')('') // =\u003e 'foo'\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?R.defaultTo('foo')('bar')%20%2F%2F%20%3D%3E%20'bar'%0AR.defaultTo('foo'))(undefined)%20%2F%2F%20%3D%3E%20'foo'%0A%0A%2F%2F%20Important%20-%20emtpy%20string%20is%20not%20falsy%20value%0Aconst%20result%20%3D%20R.defaultTo('foo')('')%20%2F%2F%20%3D%3E%20'foo'\"\u003eTry this \u003cstrong\u003eR.defaultTo\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\ndefaultTo\u003cT\u003e(defaultValue: T): (input: unknown) =\u003e T;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.defaultTo\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nfunction isFalsy(input) {\n  return input === undefined || input === null || Number.isNaN(input) === true\n}\n\nexport function defaultTo(defaultArgument, input) {\n  if (arguments.length === 1) {\n    return _input =\u003e defaultTo(defaultArgument, _input)\n  }\n\n  return isFalsy(input) ? defaultArgument : input\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { defaultTo } from './defaultTo.js'\n\ntest('with undefined', () =\u003e {\n  expect(defaultTo('foo')(undefined)).toBe('foo')\n})\n\ntest('with null', () =\u003e {\n  expect(defaultTo('foo')(null)).toBe('foo')\n})\n\ntest('with NaN', () =\u003e {\n  expect(defaultTo('foo')(Number.NaN)).toBe('foo')\n})\n\ntest('with empty string', () =\u003e {\n  expect(defaultTo('foo', '')).toBe('')\n})\n\ntest('with false', () =\u003e {\n  expect(defaultTo('foo', false)).toBeFalsy()\n})\n\ntest('when inputArgument passes initial check', () =\u003e {\n  expect(defaultTo('foo', 'bar')).toBe('bar')\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { defaultTo, pipe } from 'rambda'\n\ndescribe('R.defaultTo', () =\u003e {\n  it('happy', () =\u003e {\n    const result = pipe('bar' as unknown, defaultTo('foo'))\n\n    result // $ExpectType string\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#defaultTo)\n\n### descend\n\nHelper function to be used with `R.sort` to sort list in descending order.\n\n```javascript\nconst result = R.pipe(\n\t[{a: 1}, {a: 2}, {a: 0}],\n\tR.sort(R.descend(R.prop('a')))\n)\n// =\u003e [{a: 2}, {a: 1}, {a: 0}]\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20result%20%3D%20R.pipe(%0A%09%5B%7Ba%3A%201%7D%2C%20%7Ba%3A%202%7D%2C%20%7Ba%3A%200%7D%5D%2C%0A%09R.sort(R.descend(R.prop('a')))%0A)%0A%2F%2F%20%3D%3E%20%5B%7Ba%3A%202%7D%2C%20%7Ba%3A%201%7D%2C%20%7Ba%3A%200%7D%5D\"\u003eTry this \u003cstrong\u003eR.descend\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#descend)\n\n### drop\n\n```typescript\n\ndrop\u003cT\u003e(howMany: number): (list: T[]) =\u003e T[]\n```\n\nIt returns `howMany` items dropped from beginning of list.\n\n```javascript\nR.drop(2)(['foo', 'bar', 'baz']) // =\u003e ['baz']\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20result%20%3D%20R.drop(2)(%5B'foo'%2C%20'bar'%2C%20'baz'%5D)%20%2F%2F%20%3D%3E%20%5B'baz'%5D\"\u003eTry this \u003cstrong\u003eR.drop\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\ndrop\u003cT\u003e(howMany: number): (list: T[]) =\u003e T[];\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.drop\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function drop(howManyToDrop, listOrString) {\n  if (arguments.length === 1) {\n    return _list =\u003e drop(howManyToDrop, _list)\n  }\n\n  return listOrString.slice(howManyToDrop \u003e 0 ? howManyToDrop : 0)\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport assert from 'node:assert'\n\nimport { drop } from './drop.js'\n\ntest('with array', () =\u003e {\n  expect(drop(2)(['foo', 'bar', 'baz'])).toEqual(['baz'])\n  expect(drop(3, ['foo', 'bar', 'baz'])).toEqual([])\n  expect(drop(4, ['foo', 'bar', 'baz'])).toEqual([])\n})\n\ntest('with string', () =\u003e {\n  expect(drop(3, 'rambda')).toBe('bda')\n})\n\ntest('with non-positive count', () =\u003e {\n  expect(drop(0, [1, 2, 3])).toEqual([1, 2, 3])\n  expect(drop(-1, [1, 2, 3])).toEqual([1, 2, 3])\n  expect(drop(Number.NEGATIVE_INFINITY, [1, 2, 3])).toEqual([1, 2, 3])\n})\n\ntest('should return copy', () =\u003e {\n  const xs = [1, 2, 3]\n\n  assert.notStrictEqual(drop(0, xs), xs)\n  assert.notStrictEqual(drop(-1, xs), xs)\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { drop, pipe } from 'rambda'\n\nit('R.drop', () =\u003e {\n  const result = pipe([1, 2, 3, 4], drop(2))\n  result // $ExpectType number[]\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#drop)\n\n### dropLast\n\n```typescript\n\ndropLast\u003cT\u003e(howMany: number): (list: T[]) =\u003e T[]\n```\n\nIt returns `howMany` items dropped from the end of list.\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\ndropLast\u003cT\u003e(howMany: number): (list: T[]) =\u003e T[];\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.dropLast\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function dropLast(numberItems) {\n  return list =\u003e (numberItems \u003e 0 ? list.slice(0, -numberItems) : list.slice())\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { dropLast } from './dropLast.js'\n\ntest('with array', () =\u003e {\n  expect(dropLast(2)(['foo', 'bar', 'baz'])).toEqual(['foo'])\n  expect(dropLast(3)(['foo', 'bar', 'baz'])).toEqual([])\n  expect(dropLast(4)(['foo', 'bar', 'baz'])).toEqual([])\n})\n\ntest('with non-positive count', () =\u003e {\n  expect(dropLast(0)([1, 2, 3])).toEqual([1, 2, 3])\n  expect(dropLast(-1)([1, 2, 3])).toEqual([1, 2, 3])\n  expect(dropLast(Number.NEGATIVE_INFINITY)([1, 2, 3])).toEqual([1, 2, 3])\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#dropLast)\n\n### dropLastWhile\n\n```javascript\nconst list = [1, 2, 3, 4, 5];\nconst predicate = x =\u003e x \u003e= 3\n\nconst result = dropLastWhile(predicate)(list);\n// =\u003e [1, 2]\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20list%20%3D%20%5B1%2C%202%2C%203%2C%204%2C%205%5D%3B%0Aconst%20predicate%20%3D%20x%20%3D%3E%20x%20%3E%3D%203%0A%0Aconst%20result%20%3D%20dropLastWhile(predicate)(list)%3B%0A%2F%2F%20%3D%3E%20%5B1%2C%202%5D\"\u003eTry this \u003cstrong\u003eR.dropLastWhile\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#dropLastWhile)\n\n### dropRepeatsBy\n\n```javascript\nconst result = R.dropRepeatsBy(\n  Math.abs,\n  [1, -1, 2, 3, -3]\n)\n// =\u003e [1, 2, 3]\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20result%20%3D%20R.dropRepeatsBy(%0A%20%20Math.abs%2C%0A%20%20%5B1%2C%20-1%2C%202%2C%203%2C%20-3%5D%0A)%0A%2F%2F%20%3D%3E%20%5B1%2C%202%2C%203%5D\"\u003eTry this \u003cstrong\u003eR.dropRepeatsBy\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#dropRepeatsBy)\n\n### dropRepeatsWith\n\n```javascript\nconst list = [{a:1,b:2}, {a:1,b:3}, {a:2, b:4}]\nconst result = R.dropRepeatsWith(R.prop('a'))(list)\n\n// =\u003e [{a:1,b:2}, {a:2, b:4}]\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20list%20%3D%20%5B%7Ba%3A1%2Cb%3A2%7D%2C%20%7Ba%3A1%2Cb%3A3%7D%2C%20%7Ba%3A2%2C%20b%3A4%7D%5D%0Aconst%20result%20%3D%20R.dropRepeatsWith(R.prop('a'))(list)%0A%0A%2F%2F%20%3D%3E%20%5B%7Ba%3A1%2Cb%3A2%7D%2C%20%7Ba%3A2%2C%20b%3A4%7D%5D\"\u003eTry this \u003cstrong\u003eR.dropRepeatsWith\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#dropRepeatsWith)\n\n### dropWhile\n\n```javascript\nconst list = [1, 2, 3, 4]\nconst predicate = x =\u003e x \u003c 3\nconst result = R.dropWhile(predicate)(list)\n// =\u003e [3, 4]\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20list%20%3D%20%5B1%2C%202%2C%203%2C%204%5D%0Aconst%20predicate%20%3D%20x%20%3D%3E%20x%20%3C%203%0Aconst%20result%20%3D%20R.dropWhile(predicate)(list)%0A%2F%2F%20%3D%3E%20%5B3%2C%204%5D\"\u003eTry this \u003cstrong\u003eR.dropWhile\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#dropWhile)\n\n### eqBy\n\n```javascript\nconst result = R.eqBy(Math.abs, 5)(-5)\n// =\u003e true\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20result%20%3D%20R.eqBy(Math.abs%2C%205)(-5)%0A%2F%2F%20%3D%3E%20true\"\u003eTry this \u003cstrong\u003eR.eqBy\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#eqBy)\n\n### eqProps\n\nIt returns `true` if property `prop` in `obj1` is equal to property `prop` in `obj2` according to `R.equals`.\n\n```javascript\nconst obj1 = {a: 1, b:2}\nconst obj2 = {a: 1, b:3}\nconst result = R.eqProps('a', obj1)(obj2)\n// =\u003e true\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20obj1%20%3D%20%7Ba%3A%201%2C%20b%3A2%7D%0Aconst%20obj2%20%3D%20%7Ba%3A%201%2C%20b%3A3%7D%0Aconst%20result%20%3D%20R.eqProps('a'%2C%20obj1)(obj2)%0A%2F%2F%20%3D%3E%20true\"\u003eTry this \u003cstrong\u003eR.eqProps\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#eqProps)\n\n### equals\n\n```typescript\n\nequals\u003cT\u003e(x: T, y: T): boolean\n```\n\nIt deeply compares `x` and `y` and returns `true` if they are equal.\n\n\u003e :boom: It doesn't handle cyclical data structures and functions\n\n```javascript\nR.equals(\n  [1, {a:2}, [{b: 3}]],\n  [1, {a:2}, [{b: 3}]]\n) // =\u003e true\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?R.equals(%0A%20%20%5B1%2C%20%7Ba%3A2%7D%2C%20%5B%7Bb%3A%203%7D%5D%5D%2C%0A%20%20%5B1%2C%20%7Ba%3A2%7D%2C%20%5B%7Bb%3A%203%7D%5D%5D%0Aconst%20result%20%3D%20)%20%2F%2F%20%3D%3E%20true\"\u003eTry this \u003cstrong\u003eR.equals\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nequals\u003cT\u003e(x: T, y: T): boolean;\nequals\u003cT\u003e(x: T): (y: T) =\u003e boolean;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.equals\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nimport { isArray } from './_internals/isArray.js'\nimport { type } from './type.js'\n\nexport function _lastIndexOf(valueToFind, list) {\n  if (!isArray(list)) {\n    throw new Error(`Cannot read property 'indexOf' of ${list}`)\n  }\n\n  const typeOfValue = type(valueToFind)\n  if (!['Array', 'NaN', 'Object', 'RegExp'].includes(typeOfValue)) {\n    return list.lastIndexOf(valueToFind)\n  }\n\n  const { length } = list\n  let index = length\n  let foundIndex = -1\n\n  while (--index \u003e -1 \u0026\u0026 foundIndex === -1) {\n    if (equalsFn(list[index], valueToFind)) {\n      foundIndex = index\n    }\n  }\n\n  return foundIndex\n}\n\nexport function _indexOf(valueToFind, list) {\n  if (!isArray(list)) {\n    throw new Error(`Cannot read property 'indexOf' of ${list}`)\n  }\n\n  const typeOfValue = type(valueToFind)\n  if (!['Array', 'NaN', 'Object', 'RegExp'].includes(typeOfValue)) {\n    return list.indexOf(valueToFind)\n  }\n\n  let index = -1\n  let foundIndex = -1\n  const { length } = list\n\n  while (++index \u003c length \u0026\u0026 foundIndex === -1) {\n    if (equalsFn(list[index], valueToFind)) {\n      foundIndex = index\n    }\n  }\n\n  return foundIndex\n}\n\nfunction _arrayFromIterator(iter) {\n  const list = []\n  let next\n  while (!(next = iter.next()).done) {\n    list.push(next.value)\n  }\n\n  return list\n}\n\nfunction _compareSets(a, b) {\n  if (a.size !== b.size) {\n    return false\n  }\n\n  const aList = _arrayFromIterator(a.values())\n  const bList = _arrayFromIterator(b.values())\n\n  const filtered = aList.filter(aInstance =\u003e _indexOf(aInstance, bList) === -1)\n\n  return filtered.length === 0\n}\n\nfunction compareErrors(a, b) {\n  if (a.message !== b.message) {\n    return false\n  }\n  if (a.toString !== b.toString) {\n    return false\n  }\n\n  return a.toString() === b.toString()\n}\n\nfunction parseDate(maybeDate) {\n  if (!maybeDate.toDateString) {\n    return [false]\n  }\n\n  return [true, maybeDate.getTime()]\n}\n\nfunction parseRegex(maybeRegex) {\n  if (maybeRegex.constructor !== RegExp) {\n    return [false]\n  }\n\n  return [true, maybeRegex.toString()]\n}\n\nexport function equalsFn(a, b) {\n  if (Object.is(a, b)) {\n    return true\n  }\n\n  const aType = type(a)\n\n  if (aType !== type(b)) {\n    return false\n  }\n  if (aType === 'Function') {\n    return a.name === undefined ? false : a.name === b.name\n  }\n\n  if (['NaN', 'Null', 'Undefined'].includes(aType)) {\n    return true\n  }\n\n  if (['BigInt', 'Number'].includes(aType)) {\n    if (Object.is(-0, a) !== Object.is(-0, b)) {\n      return false\n    }\n\n    return a.toString() === b.toString()\n  }\n\n  if (['Boolean', 'String'].includes(aType)) {\n    return a.toString() === b.toString()\n  }\n\n  if (aType === 'Array') {\n    const aClone = Array.from(a)\n    const bClone = Array.from(b)\n\n    if (aClone.toString() !== bClone.toString()) {\n      return false\n    }\n\n    let loopArrayFlag = true\n    aClone.forEach((aCloneInstance, aCloneIndex) =\u003e {\n      if (loopArrayFlag) {\n        if (\n          aCloneInstance !== bClone[aCloneIndex] \u0026\u0026\n          !equalsFn(aCloneInstance, bClone[aCloneIndex])\n        ) {\n          loopArrayFlag = false\n        }\n      }\n    })\n\n    return loopArrayFlag\n  }\n\n  const aRegex = parseRegex(a)\n  const bRegex = parseRegex(b)\n\n  if (aRegex[0]) {\n    return bRegex[0] ? aRegex[1] === bRegex[1] : false\n  }\n  if (bRegex[0]) {\n    return false\n  }\n\n  const aDate = parseDate(a)\n  const bDate = parseDate(b)\n\n  if (aDate[0]) {\n    return bDate[0] ? aDate[1] === bDate[1] : false\n  }\n  if (bDate[0]) {\n    return false\n  }\n\n  if (a instanceof Error) {\n    if (!(b instanceof Error)) {\n      return false\n    }\n\n    return compareErrors(a, b)\n  }\n\n  if (aType === 'Set') {\n    return _compareSets(a, b)\n  }\n\n  if (aType === 'Object') {\n    const aKeys = Object.keys(a)\n\n    if (aKeys.length !== Object.keys(b).length) {\n      return false\n    }\n\n    let loopObjectFlag = true\n    aKeys.forEach(aKeyInstance =\u003e {\n      if (loopObjectFlag) {\n        const aValue = a[aKeyInstance]\n        const bValue = b[aKeyInstance]\n\n        if (aValue !== bValue \u0026\u0026 !equalsFn(aValue, bValue)) {\n          loopObjectFlag = false\n        }\n      }\n    })\n\n    return loopObjectFlag\n  }\n\n  return false\n}\nexport function equals(a) {\n  return b =\u003e equalsFn(a, b)\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { equalsFn } from './equals.js'\n\ntest('compare functions', () =\u003e {\n  function foo() {}\n  function bar() {}\n  const baz = () =\u003e {}\n\n  const expectTrue = equalsFn(foo, foo)\n  const expectFalseFirst = equalsFn(foo, bar)\n  const expectFalseSecond = equalsFn(foo, baz)\n\n  expect(expectTrue).toBeTruthy()\n  expect(expectFalseFirst).toBeFalsy()\n  expect(expectFalseSecond).toBeFalsy()\n})\n\ntest('with array of objects', () =\u003e {\n  const list1 = [{ a: 1 }, [{ b: 2 }]]\n  const list2 = [{ a: 1 }, [{ b: 2 }]]\n  const list3 = [{ a: 1 }, [{ b: 3 }]]\n\n  expect(equalsFn(list1, list2)).toBeTruthy()\n  expect(equalsFn(list1, list3)).toBeFalsy()\n})\n\ntest('with regex', () =\u003e {\n  expect(equalsFn(/s/, /s/)).toBeTruthy()\n  expect(equalsFn(/s/, /d/)).toBeFalsy()\n  expect(equalsFn(/a/gi, /a/gi)).toBeTruthy()\n  expect(equalsFn(/a/gim, /a/gim)).toBeTruthy()\n  expect(equalsFn(/a/gi, /a/i)).toBeFalsy()\n})\n\ntest('not a number', () =\u003e {\n  expect(equalsFn([Number.NaN], [Number.NaN])).toBeTruthy()\n})\n\ntest('new number', () =\u003e {\n  expect(equalsFn(new Number(0), new Number(0))).toBeTruthy()\n  expect(equalsFn(new Number(0), new Number(1))).toBeFalsy()\n  expect(equalsFn(new Number(1), new Number(0))).toBeFalsy()\n})\n\ntest('new string', () =\u003e {\n  expect(equalsFn(new String(''), new String(''))).toBeTruthy()\n  expect(equalsFn(new String(''), new String('x'))).toBeFalsy()\n  expect(equalsFn(new String('x'), new String(''))).toBeFalsy()\n  expect(equalsFn(new String('foo'), new String('foo'))).toBeTruthy()\n  expect(equalsFn(new String('foo'), new String('bar'))).toBeFalsy()\n  expect(equalsFn(new String('bar'), new String('foo'))).toBeFalsy()\n})\n\ntest('new Boolean', () =\u003e {\n  expect(equalsFn(new Boolean(true), new Boolean(true))).toBeTruthy()\n  expect(equalsFn(new Boolean(false), new Boolean(false))).toBeTruthy()\n  expect(equalsFn(new Boolean(true), new Boolean(false))).toBeFalsy()\n  expect(equalsFn(new Boolean(false), new Boolean(true))).toBeFalsy()\n})\n\ntest('new Error', () =\u003e {\n  expect(equalsFn(new Error('XXX'), {})).toBeFalsy()\n  expect(equalsFn(new Error('XXX'), new TypeError('XXX'))).toBeFalsy()\n  expect(equalsFn(new Error('XXX'), new Error('YYY'))).toBeFalsy()\n  expect(equalsFn(new Error('XXX'), new Error('XXX'))).toBeTruthy()\n  expect(equalsFn(new Error('XXX'), new TypeError('YYY'))).toBeFalsy()\n  expect(equalsFn(new Error('XXX'), new Error('XXX'))).toBeTruthy()\n})\n\ntest('with dates', () =\u003e {\n  expect(equalsFn(new Date(0), new Date(0))).toBeTruthy()\n  expect(equalsFn(new Date(1), new Date(1))).toBeTruthy()\n  expect(equalsFn(new Date(0), new Date(1))).toBeFalsy()\n  expect(equalsFn(new Date(1), new Date(0))).toBeFalsy()\n  expect(equalsFn(new Date(0), {})).toBeFalsy()\n  expect(equalsFn({}, new Date(0))).toBeFalsy()\n})\n\ntest('ramda spec', () =\u003e {\n  expect(equalsFn({}, {})).toBeTruthy()\n\n  expect(\n    equalsFn(\n      {\n        a: 1,\n        b: 2,\n      },\n      {\n        a: 1,\n        b: 2,\n      },\n    ),\n  ).toBeTruthy()\n\n  expect(\n    equalsFn(\n      {\n        a: 2,\n        b: 3,\n      },\n      {\n        a: 2,\n        b: 3,\n      },\n    ),\n  ).toBeTruthy()\n\n  expect(\n    equalsFn(\n      {\n        a: 2,\n        b: 3,\n      },\n      {\n        a: 3,\n        b: 3,\n      },\n    ),\n  ).toBeFalsy()\n\n  expect(\n    equalsFn(\n      {\n        a: 2,\n        b: 3,\n        c: 1,\n      },\n      {\n        a: 2,\n        b: 3,\n      },\n    ),\n  ).toBeFalsy()\n})\n\ntest('works with boolean tuple', () =\u003e {\n  expect(equalsFn([true, false], [true, false])).toBeTruthy()\n  expect(equalsFn([true, false], [true, true])).toBeFalsy()\n})\n\ntest('works with equal objects within array', () =\u003e {\n  const objFirst = {\n    a: {\n      b: 1,\n      c: 2,\n      d: [1],\n    },\n  }\n  const objSecond = {\n    a: {\n      b: 1,\n      c: 2,\n      d: [1],\n    },\n  }\n\n  const x = [1, 2, objFirst, null, '', []]\n  const y = [1, 2, objSecond, null, '', []]\n  expect(equalsFn(x, y)).toBeTruthy()\n})\n\ntest('works with different objects within array', () =\u003e {\n  const objFirst = { a: { b: 1 } }\n  const objSecond = { a: { b: 2 } }\n\n  const x = [1, 2, objFirst, null, '', []]\n  const y = [1, 2, objSecond, null, '', []]\n  expect(equalsFn(x, y)).toBeFalsy()\n})\n\ntest('works with undefined as second argument', () =\u003e {\n  expect(equalsFn(1, undefined)).toBeFalsy()\n\n  expect(equalsFn(undefined, undefined)).toBeTruthy()\n})\n\ntest('compare sets', () =\u003e {\n  const toCompareDifferent = new Set([{ a: 1 }, { a: 2 }])\n  const toCompareSame = new Set([{ a: 1 }, { a: 2 }, { a: 1 }])\n  const testSet = new Set([{ a: 1 }, { a: 2 }, { a: 1 }])\n  expect(equalsFn(toCompareSame, testSet)).toBeTruthy()\n  expect(equalsFn(toCompareDifferent, testSet)).toBeFalsy()\n})\n\ntest('compare simple sets', () =\u003e {\n  const testSet = new Set(['2', '3', '3', '2', '1'])\n  expect(equalsFn(new Set(['3', '2', '1']), testSet)).toBeTruthy()\n  expect(equalsFn(new Set(['3', '2', '0']), testSet)).toBeFalsy()\n})\n\ntest('various examples', () =\u003e {\n  expect(equalsFn([1, 2, 3], [1, 2, 3])).toBeTruthy()\n  expect(equalsFn([1, 2, 3], [1, 2])).toBeFalsy()\n  expect(equalsFn({}, {})).toBeTruthy()\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { equals } from 'rambda'\n\ndescribe('R.equals', () =\u003e {\n  it('happy', () =\u003e {\n    const result = equals(4, 1)\n    result // $ExpectType boolean\n  })\n  it('with object', () =\u003e {\n    const foo = { a: 1 }\n    const bar = { a: 2 }\n    const result = equals(foo, bar)\n    result // $ExpectType boolean\n  })\n  it('curried', () =\u003e {\n    const result = equals(4)(1)\n\n    result // $ExpectType boolean\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#equals)\n\n### evolve\n\n```typescript\n\nevolve\u003cT\u003e(rules: {\n\t[K in keyof T]?: (x: T[K]) =\u003e T[K]\n}): (obj: T) =\u003e T\n```\n\nIt takes object of functions as set of rules. These `rules` are applied to the `iterable` input to produce the result.\nIt doesn't support nested rules, i.e rules are only one level deep.\n\n```javascript\nconst input = {\n\tfoo: 2,\n\tbaz: 'baz',\n}\nconst result = R.pipe(\n\tinput, \n\tevolve({\n\t\tfoo: x =\u003e x + 1,\n\t})\n)\n// =\u003e result is { foo: 3, baz: 'baz' }\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20input%20%3D%20%7B%0A%09foo%3A%202%2C%0A%09baz%3A%20'baz'%2C%0A%7D%0Aconst%20result%20%3D%20R.pipe(%0A%09input%2C%20%0A%09evolve(%7B%0A%09%09foo%3A%20x%20%3D%3E%20x%20%2B%201%2C%0A%09%7D)%0A)%0A%2F%2F%20%3D%3E%20result%20is%20%7B%20foo%3A%203%2C%20baz%3A%20'baz'%20%7D\"\u003eTry this \u003cstrong\u003eR.evolve\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nevolve\u003cT\u003e(rules: {\n\t[K in keyof T]?: (x: T[K]) =\u003e T[K]\n}): (obj: T) =\u003e T;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.evolve\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nimport { mapObject } from './mapObject.js'\nimport { type } from './type.js'\n\nexport function evolve(rules) {\n  return mapObject((x, prop) =\u003e type(rules[prop]) === 'Function' ? rules[prop](x): x)\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { evolve } from './evolve.js'\n\ntest('happy', () =\u003e {\n  const rules = {\n    foo: x =\u003e x + 1,\n  }\n  const input = {\n    a: 1,\n    foo: 2,\n\t\tnested: { bar: { z: 3 } },\n  }\n  const result = evolve(rules)(input)\n  expect(result).toEqual({\n    a: 1,\n    foo: 3,\n\t\tnested: { bar: { z: 3 } },\n  })\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport {  evolve, pipe } from 'rambda'\n\nit('R.evolve', () =\u003e {\n  const input = {\n\t\tbaz: 1,\n    foo: 2,\n    nested: {\n      a: 1,\n      bar: 3,\n    },\n  }\n  const result = pipe(input, \n\t\tevolve({\n\t\t\tfoo: x =\u003e x + 1,\n\t\t})\n\t)\n  result.foo // $ExpectType number\n  result.baz // $ExpectType number\n  result.nested.a // $ExpectType number\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#evolve)\n\n### excludes\n\nOpposite of `R.includes`\n\n`R.equals` is used to determine equality.\n\n```javascript\nconst result = [\n  R.excludes('ar')('foo'),\n  R.excludes({a: 2})([{a: 1}])\n]\n// =\u003e [true, true ]\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20result%20%3D%20%5B%0A%20%20R.excludes('ar')('foo')%2C%0A%20%20R.excludes(%7Ba%3A%202%7D)(%5B%7Ba%3A%201%7D%5D)%0A%5D%0A%2F%2F%20%3D%3E%20%5Btrue%2C%20true%20%5D\"\u003eTry this \u003cstrong\u003eR.excludes\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#excludes)\n\n### filter\n\n```typescript\n\nfilter\u003cT, S extends T\u003e(\n  predicate: (value: T) =\u003e value is S,\n): (list: T[]) =\u003e S[]\n```\n\nIt filters list or object `input` using a `predicate` function.\n\n```javascript\nconst predicate = x =\u003e x \u003e 1\nconst list = [1, 2, 3]\nconst result = R.filter(predicate)(list)\n// =\u003e [2, 3]\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20predicate%20%3D%20x%20%3D%3E%20x%20%3E%201%0Aconst%20list%20%3D%20%5B1%2C%202%2C%203%5D%0Aconst%20result%20%3D%20R.filter(predicate)(list)%0A%2F%2F%20%3D%3E%20%5B2%2C%203%5D\"\u003eTry this \u003cstrong\u003eR.filter\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nfilter\u003cT, S extends T\u003e(\n  predicate: (value: T) =\u003e value is S,\n): (list: T[]) =\u003e S[];\nfilter\u003cT\u003e(\n\tpredicate: BooleanConstructor,\n): (list: readonly T[]) =\u003e StrictNonNullable\u003cT\u003e[];\nfilter\u003cT\u003e(\n\tpredicate: BooleanConstructor,\n): (list: T[]) =\u003e StrictNonNullable\u003cT\u003e[];\nfilter\u003cT\u003e(\n\tpredicate: (value: T) =\u003e boolean,\n): (list: T[]) =\u003e T[];\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.filter\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function filter(predicate) {\n  return list =\u003e {\n    if (!list) {\n      throw new Error('Incorrect iterable input')\n    }\n    let index = 0\n    const len = list.length\n    const willReturn = []\n\n    while (index \u003c len) {\n      if (predicate(list[index], index)) {\n        willReturn.push(list[index])\n      }\n\n      index++\n    }\n\n    return willReturn\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { filter } from './filter.js'\n\ntest('happy', () =\u003e {\n  const isEven = n =\u003e n % 2 === 0\n\n  expect(filter(isEven)([1, 2, 3, 4])).toEqual([2, 4])\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { filter, mergeTypes, pipe } from 'rambda'\n\nconst list = [1, 2, 3]\n\ndescribe('R.filter with array', () =\u003e {\n  it('within pipe', () =\u003e {\n    const result = pipe(\n      list,\n      filter(x =\u003e {\n        x // $ExpectType number\n        return x \u003e 1\n      }),\n    )\n    result // $ExpectType number[]\n  })\n  it('narrowing type', () =\u003e {\n    interface Foo {\n      a: number\n    }\n    interface Bar extends Foo {\n      b: string\n    }\n\t\ttype T = Foo | Bar\n    const testList: T[]= [{ a: 1 }, { a: 2 }, { a: 3 }] \n    const filterBar = (x: T): x is Bar =\u003e {\n      return typeof (x as Bar).b === 'string'\n    }\n    const result = pipe(\n      testList,\n      filter(filterBar),\n    )\n    result // $ExpectType Bar[]\n  })\n  it('narrowing type - readonly', () =\u003e {\n    interface Foo {\n      a: number\n    }\n    interface Bar extends Foo {\n      b: string\n    }\n\t\ttype T = Foo | Bar\n    const testList: T[]= [{ a: 1 }, { a: 2 }, { a: 3 }] as const\n    const filterBar = (x: T): x is Bar =\u003e {\n      return typeof (x as Bar).b === 'string'\n    }\n    const result = pipe(\n      testList,\n      filter(filterBar),\n    )\n    result // $ExpectType Bar[]\n  })\n  it('filtering NonNullable', () =\u003e {\n    const testList = [1, 2, null, undefined, 3]\n    const result = pipe(testList, filter(Boolean))\n    result // $ExpectType number[]\n  })\n  it('filtering NonNullable - readonly', () =\u003e {\n    const testList = [1, 2, null, undefined, 3] as const\n    const result = pipe(testList, filter(Boolean))\n    result.includes(1)\n    // @ts-expect-error\n    result.includes(4)\n    // @ts-expect-error\n    result.includes(undefined) \n    // @ts-expect-error\n    result.includes(null)\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#filter)\n\n### filterObject\n\n```typescript\n\nfilterObject\u003cT extends object\u003e(\n  valueMapper: (\n    value: EnumerableStringKeyedValueOf\u003cT\u003e,\n    key: EnumerableStringKeyOf\u003cT\u003e,\n    data: T,\n  ) =\u003e boolean,\n): \u003cU extends T\u003e(data: T) =\u003e U\n```\n\nIt loops over each property of `obj` and returns a new object with only those properties that satisfy the `predicate`.\n\n```javascript\nconst result = R.filterObject(\n\t(val, prop) =\u003e prop === 'a' || val \u003e 1\n)({a: 1, b: 2, c:3})\n// =\u003e {a: 1, c: 3}\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20result%20%3D%20R.filterObject(%0A%09(val%2C%20prop)%20%3D%3E%20prop%20%3D%3D%3D%20'a'%20%7C%7C%20val%20%3E%201%0A)(%7Ba%3A%201%2C%20b%3A%202%2C%20c%3A3%7D)%0A%2F%2F%20%3D%3E%20%7Ba%3A%201%2C%20c%3A%203%7D\"\u003eTry this \u003cstrong\u003eR.filterObject\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nfilterObject\u003cT extends object\u003e(\n  valueMapper: (\n    value: EnumerableStringKeyedValueOf\u003cT\u003e,\n    key: EnumerableStringKeyOf\u003cT\u003e,\n    data: T,\n  ) =\u003e boolean,\n): \u003cU extends T\u003e(data: T) =\u003e U;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.filterObject\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function filterObject(predicate) {\n  return obj =\u003e {\n    const willReturn = {}\n\n    for (const prop in obj) {\n      if (predicate(obj[prop], prop, obj)) {\n        willReturn[prop] = obj[prop]\n      }\n    }\n\n    return willReturn\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { pipe } from './pipe.js'\nimport { filterObject } from './filterObject.js'\n\ntest('happy', () =\u003e {\n\tlet testInput = { a: 1, b: 2, c: 3 }\n  const result = pipe(\n\t\ttestInput,\n\t\tfilterObject((x, prop, obj) =\u003e {\n\t\t\texpect(prop).toBeOneOf(['a', 'b', 'c'])\n\t\t\texpect(obj).toBe(testInput)\n\t\t\treturn x \u003e 1\n\t\t})\n\t)\n\texpect(result).toEqual({ b: 2, c: 3 })\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { filterObject, pipe } from 'rambda'\n\ndescribe('R.filterObject', () =\u003e {\n  it('require explicit type', () =\u003e {\n    const result = pipe(\n      { a: 1, b: 2 },\n      filterObject\u003c{ b: number }\u003e(a =\u003e {\n        a // $ExpectType number\n        return a \u003e 1\n      }),\n    )\n    result.b // $ExpectType number\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#filterObject)\n\n### find\n\n```typescript\n\nfind\u003cT\u003e(predicate: (x: T) =\u003e boolean): (list: T[]) =\u003e T | undefined\n```\n\nIt returns the first element of `list` that satisfy the `predicate`.\n\nIf there is no such element, it returns `undefined`.\n\n```javascript\nconst predicate = x =\u003e R.type(x.foo) === 'Number'\nconst list = [{foo: 'bar'}, {foo: 1}]\n\nconst result = R.find(predicate)(list)\n// =\u003e {foo: 1}\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20predicate%20%3D%20x%20%3D%3E%20R.type(x.foo)%20%3D%3D%3D%20'Number'%0Aconst%20list%20%3D%20%5B%7Bfoo%3A%20'bar'%7D%2C%20%7Bfoo%3A%201%7D%5D%0A%0Aconst%20result%20%3D%20R.find(predicate)(list)%0A%2F%2F%20%3D%3E%20%7Bfoo%3A%201%7D\"\u003eTry this \u003cstrong\u003eR.find\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nfind\u003cT\u003e(predicate: (x: T) =\u003e boolean): (list: T[]) =\u003e T | undefined;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.find\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function find(predicate) {\n  return list =\u003e {\n    let index = 0\n    const len = list.length\n\n    while (index \u003c len) {\n      const x = list[index]\n      if (predicate(x)) {\n        return x\n      }\n\n      index++\n    }\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { find } from './find.js'\nimport { propEq } from './propEq.js'\n\nconst list = [{ a: 1 }, { a: 2 }, { a: 3 }]\n\ntest('happy', () =\u003e {\n  const fn = propEq(2, 'a')\n  expect(find(fn)(list)).toEqual({ a: 2 })\n})\n\ntest('nothing is found', () =\u003e {\n  const fn = propEq(4, 'a')\n  expect(find(fn)(list)).toBeUndefined()\n})\n\ntest('with empty list', () =\u003e {\n  expect(find(() =\u003e true)([])).toBeUndefined()\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { find, pipe } from 'rambda'\n\nconst list = [1, 2, 3]\n\ndescribe('R.find', () =\u003e {\n  it('happy', () =\u003e {\n    const predicate = (x: number) =\u003e x \u003e 2\n    const result = pipe(list, find(predicate))\n    result // $ExpectType number | undefined\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#find)\n\n### findIndex\n\n```typescript\n\nfindIndex\u003cT\u003e(predicate: (x: T) =\u003e boolean): (list: T[]) =\u003e number\n```\n\nIt returns the index of the first element of `list` satisfying the `predicate` function.\n\nIf there is no such element, then `-1` is returned.\n\n```javascript\nconst predicate = x =\u003e R.type(x.foo) === 'Number'\nconst list = [{foo: 'bar'}, {foo: 1}]\n\nconst result = R.findIndex(predicate)(list)\n// =\u003e 1\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20predicate%20%3D%20x%20%3D%3E%20R.type(x.foo)%20%3D%3D%3D%20'Number'%0Aconst%20list%20%3D%20%5B%7Bfoo%3A%20'bar'%7D%2C%20%7Bfoo%3A%201%7D%5D%0A%0Aconst%20result%20%3D%20R.findIndex(predicate)(list)%0A%2F%2F%20%3D%3E%201\"\u003eTry this \u003cstrong\u003eR.findIndex\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nfindIndex\u003cT\u003e(predicate: (x: T) =\u003e boolean): (list: T[]) =\u003e number;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.findIndex\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function findIndex(predicate) {\n  return list =\u003e {\n    const len = list.length\n    let index = -1\n\n    while (++index \u003c len) {\n      if (predicate(list[index])) {\n        return index\n      }\n    }\n\n    return -1\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { findIndex } from './findIndex.js'\nimport { propEq } from './propEq.js'\n\nconst list = [{ a: 1 }, { a: 2 }, { a: 3 }]\n\ntest('happy', () =\u003e {\n  expect(findIndex(propEq(2, 'a'))(list)).toBe(1)\n  expect(findIndex(propEq(1, 'a'))(list)).toBe(0)\n  expect(findIndex(propEq(4, 'a'))(list)).toBe(-1)\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { findIndex, pipe } from 'rambda'\n\nconst list = [1, 2, 3]\n\nit('R.findIndex', () =\u003e {\n  const result = pipe(\n    list,\n    findIndex(x =\u003e x \u003e 2),\n  )\n  result // $ExpectType number\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#findIndex)\n\n### findLast\n\n```typescript\n\nfindLast\u003cT\u003e(fn: (x: T) =\u003e boolean): (list: T[]) =\u003e T | undefined\n```\n\nIt returns the last element of `list` satisfying the `predicate` function.\n\nIf there is no such element, then `undefined` is returned.\n\n```javascript\nconst predicate = x =\u003e R.type(x.foo) === 'Number'\nconst list = [{foo: 0}, {foo: 1}]\n\nconst result = R.findLast(predicate)(list)\n// =\u003e {foo: 1}\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20predicate%20%3D%20x%20%3D%3E%20R.type(x.foo)%20%3D%3D%3D%20'Number'%0Aconst%20list%20%3D%20%5B%7Bfoo%3A%200%7D%2C%20%7Bfoo%3A%201%7D%5D%0A%0Aconst%20result%20%3D%20R.findLast(predicate)(list)%0A%2F%2F%20%3D%3E%20%7Bfoo%3A%201%7D\"\u003eTry this \u003cstrong\u003eR.findLast\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nfindLast\u003cT\u003e(fn: (x: T) =\u003e boolean): (list: T[]) =\u003e T | undefined;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.findLast\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function findLast(predicate) {\n  return list =\u003e {\n    let index = list.length\n\n    while (--index \u003e= 0) {\n      if (predicate(list[index])) {\n        return list[index]\n      }\n    }\n\n    return undefined\n  }\n}\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#findLast)\n\n### findLastIndex\n\n```typescript\n\nfindLastIndex\u003cT\u003e(predicate: (x: T) =\u003e boolean): (list: T[]) =\u003e number\n```\n\nIt returns the index of the last element of `list` satisfying the `predicate` function.\n\nIf there is no such element, then `-1` is returned.\n\n```javascript\nconst predicate = x =\u003e R.type(x.foo) === 'Number'\nconst list = [{foo: 0}, {foo: 1}]\n\nconst result = R.findLastIndex(predicate)(list)\n// =\u003e 1\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20predicate%20%3D%20x%20%3D%3E%20R.type(x.foo)%20%3D%3D%3D%20'Number'%0Aconst%20list%20%3D%20%5B%7Bfoo%3A%200%7D%2C%20%7Bfoo%3A%201%7D%5D%0A%0Aconst%20result%20%3D%20R.findLastIndex(predicate)(list)%0A%2F%2F%20%3D%3E%201\"\u003eTry this \u003cstrong\u003eR.findLastIndex\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nfindLastIndex\u003cT\u003e(predicate: (x: T) =\u003e boolean): (list: T[]) =\u003e number;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.findLastIndex\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function findLastIndex(fn) {\n  return list =\u003e {\n    let index = list.length\n\n    while (--index \u003e= 0) {\n      if (fn(list[index])) {\n        return index\n      }\n    }\n\n    return -1\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { findLastIndex } from './findLastIndex.js'\n\ntest('happy', () =\u003e {\n  const result = findLastIndex(x =\u003e x \u003e 1)([1, 1, 1, 2, 3, 4, 1])\n  expect(result).toBe(5)\n  expect(findLastIndex(x =\u003e x === 0)([0, 1, 1, 2, 3, 4, 1])).toBe(0)\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { findLastIndex, pipe } from 'rambda'\n\nconst list = [1, 2, 3]\n\ndescribe('R.findLastIndex', () =\u003e {\n  it('happy', () =\u003e {\n    const predicate = (x: number) =\u003e x \u003e 2\n    const result = pipe(list, findLastIndex(predicate))\n    result // $ExpectType number\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#findLastIndex)\n\n### findNth\n\n```typescript\n\nfindNth\u003cT\u003e(predicate: (x: T) =\u003e boolean, nth: number): (list: T[]) =\u003e T | undefined\n```\n\nIt returns the `nth` element of `list` that satisfy the `predicate` function.\n\n```javascript\nconst predicate = x =\u003e R.type(x.foo) === 'Number'\nconst list = [{foo: 0}, {foo: 1}, {foo: 2}, {foo: 3}]\n\nconst result = R.findNth(predicate, 2)(list)\n// =\u003e {foo: 2}\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20predicate%20%3D%20x%20%3D%3E%20R.type(x.foo)%20%3D%3D%3D%20'Number'%0Aconst%20list%20%3D%20%5B%7Bfoo%3A%200%7D%2C%20%7Bfoo%3A%201%7D%2C%20%7Bfoo%3A%202%7D%2C%20%7Bfoo%3A%203%7D%5D%0A%0Aconst%20result%20%3D%20R.findNth(predicate%2C%202)(list)%0A%2F%2F%20%3D%3E%20%7Bfoo%3A%202%7D\"\u003eTry this \u003cstrong\u003eR.findNth\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nfindNth\u003cT\u003e(predicate: (x: T) =\u003e boolean, nth: number): (list: T[]) =\u003e T | undefined;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.findNth\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function findNth(predicate, nth) {\n  return list =\u003e {\n    let index = 0\n    const len = list.length\n\n    while (index \u003c len) {\n      const x = list[index]\n      if (predicate(x)) {\n\t\t\t\tif (nth === 0) return x\n\t\t\t\tnth--\n      }\n\n      index++\n    }\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { findNth } from './findNth.js'\n\nconst list = [{ a: 1 }, { a: 2 }, { a: 3 }, { a: 4 }]\n\ntest('happy', () =\u003e {\n  const fn = x =\u003e x.a \u003e 1\n  expect(findNth(fn,1)(list)).toEqual({ a: 3 })\n})\n\ntest('nothing is found', () =\u003e {\n\tconst fn = x =\u003e x.a \u003e 4\n\texpect(findNth(fn,1)(list)).toBeUndefined()\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#findNth)\n\n### flatMap\n\n```typescript\n\nflatMap\u003cT, U extends unknown\u003e(transformFn: (x: T extends any[] ? T[number]: never) =\u003e U): (listOfLists: T[]) =\u003e U[]\n```\n\nIt maps `fn` over `list` and then flatten the result by one-level.\n\n```javascript\nconst duplicate = n =\u003e [ n, n ]\nconst list = [ 1, 2, 3 ]\n\nconst result = R.flatMap(duplicate)(list)\n// =\u003e [ 1, 1, 2, 2, 3, 3 ]\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20duplicate%20%3D%20n%20%3D%3E%20%5B%20n%2C%20n%20%5D%0Aconst%20list%20%3D%20%5B%201%2C%202%2C%203%20%5D%0A%0Aconst%20result%20%3D%20R.flatMap(duplicate)(list)%0A%2F%2F%20%3D%3E%20%5B%201%2C%201%2C%202%2C%202%2C%203%2C%203%20%5D\"\u003eTry this \u003cstrong\u003eR.flatMap\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nflatMap\u003cT, U extends unknown\u003e(transformFn: (x: T extends any[] ? T[number]: never) =\u003e U): (listOfLists: T[]) =\u003e U[];\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.flatMap\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function flatMap(fn) {\n  return list =\u003e [].concat(...list.map(fn))\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { flatMap } from './flatMap.js'\n\nconst duplicate = n =\u003e [n, n]\n\ntest('happy', () =\u003e {\n  const fn = x =\u003e [x * 2]\n  const list = [1, 2, 3]\n\n  const result = flatMap(fn)(list)\n\n  expect(result).toEqual([2, 4, 6])\n})\n\ntest('maps then flattens one level', () =\u003e {\n  expect(flatMap(duplicate)([1, 2, 3])).toEqual([1, 1, 2, 2, 3, 3])\n})\n\ntest('maps then flattens one level', () =\u003e {\n  expect(flatMap(duplicate)([1, 2, 3])).toEqual([1, 1, 2, 2, 3, 3])\n})\n\ntest('flattens only one level', () =\u003e {\n  const nest = n =\u003e [[n]]\n  expect(flatMap(nest)([1, 2, 3])).toEqual([[1], [2], [3]])\n})\n\ntest('can compose', () =\u003e {\n  function dec(x) {\n    return [x - 1]\n  }\n  function times2(x) {\n    return [x * 2]\n  }\n\n  const mdouble = flatMap(times2)\n  const mdec = flatMap(dec)\n  expect(mdec(mdouble([10, 20, 30]))).toEqual([19, 39, 59])\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { flatMap, pipe } from 'rambda'\n\ndescribe('R.flatMap', () =\u003e {\n  it('happy', () =\u003e {\n    const listOfLists: string[][] = [\n      ['f', 'bar'],\n      ['baz', 'b'],\n    ]\n    const result = pipe(\n      listOfLists,\n      x =\u003e x,\n      flatMap(x =\u003e {\n        x // $ExpectType string\n        return Number(x) + 1\n      }),\n    )\n    result // $ExpectType number[]\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#flatMap)\n\n### flatten\n\n```typescript\n\nflatten\u003cT\u003e(list: any[]): T[]\n```\n\nIt deeply flattens an array.\nYou must pass expected output type as a type argument.\n\n```javascript\nconst result = R.flatten\u003cnumber\u003e([\n  1, \n  2, \n  [3, 30, [300]], \n  [4]\n])\n// =\u003e [ 1, 2, 3, 30, 300, 4 ]\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20result%20%3D%20R.flatten%3Cnumber%3E(%5B%0A%20%201%2C%20%0A%20%202%2C%20%0A%20%20%5B3%2C%2030%2C%20%5B300%5D%5D%2C%20%0A%20%20%5B4%5D%0A%5D)%0A%2F%2F%20%3D%3E%20%5B%201%2C%202%2C%203%2C%2030%2C%20300%2C%204%20%5D\"\u003eTry this \u003cstrong\u003eR.flatten\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nflatten\u003cT\u003e(list: any[]): T[];\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.flatten\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nimport { isArray } from './_internals/isArray.js'\n\nexport function flatten(list, input) {\n  const willReturn = input === undefined ? [] : input\n\n  for (let i = 0; i \u003c list.length; i++) {\n    if (isArray(list[i])) {\n      flatten(list[i], willReturn)\n    } else {\n      willReturn.push(list[i])\n    }\n  }\n\n  return willReturn\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { flatten } from './flatten.js'\n\ntest('happy', () =\u003e {\n  expect(flatten([1, 2, 3, [[[[[4]]]]]])).toEqual([1, 2, 3, 4])\n\n  expect(flatten([1, [2, [[3]]], [4]])).toEqual([1, 2, 3, 4])\n\n  expect(flatten([1, [2, [[[3]]]], [4]])).toEqual([1, 2, 3, 4])\n\n  expect(flatten([1, 2, [3, 4], 5, [6, [7, 8, [9, [10, 11], 12]]]])).toEqual([\n    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,\n  ])\n})\n\ntest('readme example', () =\u003e {\n  const result = flatten([1, 2, [3, 30, [300]], [4]])\n  expect(result).toEqual([1, 2, 3, 30, 300, 4])\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { flatten, pipe } from 'rambda'\n\ndescribe('flatten', () =\u003e {\n  it('happy', () =\u003e {\n    const result = pipe([1, 2, [3, [4]]], flatten\u003cnumber\u003e)\n    result // $ExpectType number[]\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#flatten)\n\n### groupBy\n\nIt splits `list` according to a provided `groupFn` function and returns an object.\n\n```javascript\nconst list = [ 'a', 'b', 'aa', 'bb' ]\nconst groupFn = x =\u003e x.length\n\nconst result = R.groupBy(groupFn, list)\n// =\u003e { '1': ['a', 'b'], '2': ['aa', 'bb'] }\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20list%20%3D%20%5B%20'a'%2C%20'b'%2C%20'aa'%2C%20'bb'%20%5D%0Aconst%20groupFn%20%3D%20x%20%3D%3E%20x.length%0A%0Aconst%20result%20%3D%20R.groupBy(groupFn%2C%20list)%0A%2F%2F%20%3D%3E%20%7B%20'1'%3A%20%5B'a'%2C%20'b'%5D%2C%20'2'%3A%20%5B'aa'%2C%20'bb'%5D%20%7D\"\u003eTry this \u003cstrong\u003eR.groupBy\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#groupBy)\n\n### head\n\n```typescript\n\nhead\u003cT\u003e(listOrString: T): T extends string ? string : \n\tT extends [] ? undefined: \n\t\tT extends readonly [infer F, ...infer R] ? F : \n\t\t\tT extends readonly [infer F] ? F :\n\t\t\t\tT extends [infer F] ? F :\n\t\t\t\t\tT extends [infer F, ...infer R] ? F : \n\t\t\t\t\t\tT extends unknown[] ? T[number] : \n\t\t\t\t\t\t\tundefined\n```\n\nIt returns the first element of list or string `input`. It returns `undefined` if array has length of 0.\n\n```javascript\nconst result = [\n  R.head([1, 2, 3]),\n  R.head('foo') \n]\n// =\u003e [1, 'f']\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20result%20%3D%20%5B%0A%20%20R.head(%5B1%2C%202%2C%203%5D)%2C%0A%20%20R.head('foo')%20%0A%5D%0A%2F%2F%20%3D%3E%20%5B1%2C%20'f'%5D\"\u003eTry this \u003cstrong\u003eR.head\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nhead\u003cT\u003e(listOrString: T): T extends string ? string : \n\tT extends [] ? undefined: \n\t\tT extends readonly [infer F, ...infer R] ? F : \n\t\t\tT extends readonly [infer F] ? F :\n\t\t\t\tT extends [infer F] ? F :\n\t\t\t\t\tT extends [infer F, ...infer R] ? F : \n\t\t\t\t\t\tT extends unknown[] ? T[number] : \n\t\t\t\t\t\t\tundefined;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.head\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function head(listOrString) {\n  if (typeof listOrString === 'string') {\n    return listOrString[0] || ''\n  }\n\n  return listOrString[0]\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { head } from './head.js'\n\ntest('head', () =\u003e {\n  expect(head(['fi', 'fo', 'fum'])).toBe('fi')\n  expect(head([])).toBeUndefined()\n  expect(head('foo')).toBe('f')\n  expect(head('')).toBe('')\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { head, last } from 'rambda'\n\nexport const mixedList = [1, 'foo', 3, 'bar']\nexport const mixedListConst = [1, 'foo', 3, 'bar'] as const\nexport const numberList = [1, 2, 3]\nexport const numberListConst = [1, 2, 3] as const\nexport const emptyList = []\nexport const emptyString = ''\nexport const string = 'foo'\n\ndescribe('R.head', () =\u003e {\n  it('string', () =\u003e {\n    head(string) // $ExpectType string\n    last(string) // $ExpectType string\n  })\n  it('empty string', () =\u003e {\n    head(emptyString) // $ExpectType string\n    last(emptyString) // $ExpectType string\n  })\n  it('array', () =\u003e {\n    head(numberList) // $ExpectType number\n    head(numberListConst) // $ExpectType 1\n\n    last(numberList) // $ExpectType number\n    last(numberListConst) // $ExpectType 3\n  })\n  it('empty array', () =\u003e {\n    const list = [] as const\n    head(emptyList) // $ExpectType never\n    head(list) // $ExpectType undefined\n    last(emptyList) // $ExpectType never\n    last(list) // $ExpectType undefined\n  })\n\n  it('mixed', () =\u003e {\n    head(mixedList) // $ExpectType string | number\n    head(mixedListConst) // $ExpectType 1\n    last(mixedList) // $ExpectType string | number\n    last(mixedListConst) // $ExpectType \"bar\"\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#head)\n\n### includes\n\n```typescript\n\nincludes\u003cT extends string\u003e(valueToFind: T): (input: string) =\u003e boolean\n```\n\nIf `input` is string, then this method work as native `String.includes`.\n\nIf `input` is array, then `R.equals` is used to define if `valueToFind` belongs to the list.\n\n```javascript\nconst result = [\n  R.includes('oo')('foo'),\n  R.includes({a: 1})([{a: 1}])\n]\n// =\u003e [true, true ]\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20result%20%3D%20%5B%0A%20%20R.includes('oo')('foo')%2C%0A%20%20R.includes(%7Ba%3A%201%7D)(%5B%7Ba%3A%201%7D%5D)%0A%5D%0A%2F%2F%20%3D%3E%20%5Btrue%2C%20true%20%5D\"\u003eTry this \u003cstrong\u003eR.includes\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nincludes\u003cT extends string\u003e(valueToFind: T): (input: string) =\u003e boolean;\nincludes\u003cT\u003e(valueToFind: T): (input: T[]) =\u003e boolean;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.includes\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nimport { isArray } from './_internals/isArray.js'\nimport { _indexOf } from './equals.js'\n\nexport function includes(valueToFind) {\n  return iterable =\u003e {\n    if (typeof iterable === 'string') {\n      return iterable.includes(valueToFind)\n    }\n    if (!iterable) {\n      throw new TypeError(`Cannot read property \\'indexOf\\' of ${iterable}`)\n    }\n    if (!isArray(iterable)) {\n      return false\n    }\n\n    return _indexOf(valueToFind, iterable) \u003e -1\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { includes } from './includes.js'\n\ntest('with string as iterable', () =\u003e {\n  const str = 'foo bar'\n\n  expect(includes('bar')(str)).toBeTruthy()\n  expect(includes('never')(str)).toBeFalsy()\n})\n\ntest('with array as iterable', () =\u003e {\n  const arr = [1, 2, 3]\n\n  expect(includes(2)(arr)).toBeTruthy()\n  expect(includes(4)(arr)).toBeFalsy()\n})\n\ntest('with list of objects as iterable', () =\u003e {\n  const arr = [{ a: 1 }, { b: 2 }, { c: 3 }]\n\n  expect(includes({ c: 3 })(arr)).toBeTruthy()\n})\n\ntest('with NaN', () =\u003e {\n  const result = includes(Number.NaN)([Number.NaN])\n  expect(result).toBeTruthy()\n})\n\ntest('with wrong input that does not throw', () =\u003e {\n  const result = includes(1)(/foo/g)\n  expect(result).toBeFalsy()\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { includes, pipe } from 'rambda'\n\ndescribe('R.includes', () =\u003e {\n  it('happy', () =\u003e {\n    const list = [{ a: { b: '1' } }, { a: { b: '2' } }, { a: { b: '3' } }]\n    const result = pipe(list, includes({ a: { b: '1' } }))\n    result // $ExpectType boolean\n  })\n  it('with string', () =\u003e {\n    const result = pipe('foo', includes('bar'))\n    result // $ExpectType boolean\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#includes)\n\n### indexOf\n\nIt uses `R.equals` for list of objects/arrays or native `indexOf` for any other case.\n\n```javascript\nconst result = [\n  R.indexOf({a:1})([{a:1}, {a:2}]),\n  R.indexOf(2)([1, 2, 3]),\n]\n// =\u003e [0, 1]\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20result%20%3D%20%5B%0A%20%20R.indexOf(%7Ba%3A1%7D)(%5B%7Ba%3A1%7D%2C%20%7Ba%3A2%7D%5D)%2C%0A%20%20R.indexOf(2)(%5B1%2C%202%2C%203%5D)%2C%0A%5D%0A%2F%2F%20%3D%3E%20%5B0%2C%201%5D\"\u003eTry this \u003cstrong\u003eR.indexOf\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#indexOf)\n\n### init\n\n```typescript\n\ninit\u003cT extends unknown[]\u003e(input: T): T extends readonly [...infer U, any] ? U : [...T]\n```\n\nIt returns all but the last element of list or string `input`.\n\n```javascript\nconst result = [\n  R.init([1, 2, 3]) , \n  R.init('foo')  // =\u003e 'fo'\n]\n// =\u003e [[1, 2], 'fo']\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20result%20%3D%20%5B%0A%20%20R.init(%5B1%2C%202%2C%203%5D)%20%2C%20%0A%20%20R.init('foo')%20%20%2F%2F%20%3D%3E%20'fo'%0A%5D%0A%2F%2F%20%3D%3E%20%5B%5B1%2C%202%5D%2C%20'fo'%5D\"\u003eTry this \u003cstrong\u003eR.init\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\ninit\u003cT extends unknown[]\u003e(input: T): T extends readonly [...infer U, any] ? U : [...T];\ninit(input: string): string;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.init\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nimport { baseSlice } from './_internals/baseSlice.js'\n\nexport function init(input) {\n  if (typeof input === 'string') {\n    return input.slice(0, -1)\n  }\n\n  return input.length ? baseSlice(input, 0, -1) : []\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { init } from './init.js'\n\ntest('with array', () =\u003e {\n  expect(init([1, 2, 3])).toEqual([1, 2])\n  expect(init([1, 2])).toEqual([1])\n  expect(init([1])).toEqual([])\n  expect(init([])).toEqual([])\n  expect(init([])).toEqual([])\n  expect(init([1])).toEqual([])\n})\n\ntest('with string', () =\u003e {\n  expect(init('foo')).toBe('fo')\n  expect(init('f')).toBe('')\n  expect(init('')).toBe('')\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { init } from 'rambda'\n\ndescribe('R.init', () =\u003e {\n  it('with string', () =\u003e {\n    const result = init('foo')\n\n    result // $ExpectType string\n  })\n  it('with list - one type', () =\u003e {\n    const result = init([1, 2, 3])\n\n    result // $ExpectType number[]\n  })\n  it('with list - mixed types', () =\u003e {\n    const result = init([1, 2, 3, 'foo', 'bar'])\n\n    result // $ExpectType (string | number)[]\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#init)\n\n### innerJoin\n\nIt returns a new list by applying a `predicate` function to all elements of `list1` and `list2` and keeping only these elements where `predicate` returns `true`.\n\n```javascript\nconst list1 = [1, 2, 3, 4, 5]\nconst list2 = [4, 5, 6]\nconst predicate = (x, y) =\u003e x \u003e= y\nconst result = R.innerJoin(predicate, list1)(list2)\n// =\u003e [4, 5]\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20list1%20%3D%20%5B1%2C%202%2C%203%2C%204%2C%205%5D%0Aconst%20list2%20%3D%20%5B4%2C%205%2C%206%5D%0Aconst%20predicate%20%3D%20(x%2C%20y)%20%3D%3E%20x%20%3E%3D%20y%0Aconst%20result%20%3D%20R.innerJoin(predicate%2C%20list1)(list2)%0A%2F%2F%20%3D%3E%20%5B4%2C%205%5D\"\u003eTry this \u003cstrong\u003eR.innerJoin\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#innerJoin)\n\n### interpolate\n\n```typescript\n\ninterpolate(inputWithTags: string): (templateArguments: object) =\u003e string\n```\n\nIt generates a new string from `inputWithTags` by replacing all `{{x}}` occurrences with values provided by `templateArguments`.\n\n```javascript\nconst inputWithTags = 'foo is {{bar}} even {{a}} more'\nconst templateArguments = {\"bar\":\"BAR\", a: 1}\n\nconst result = R.interpolate(inputWithTags, templateArguments)\nconst expected = 'foo is BAR even 1 more'\n// =\u003e `result` is equal to `expected`\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20inputWithTags%20%3D%20'foo%20is%20%7B%7Bbar%7D%7D%20even%20%7B%7Ba%7D%7D%20more'%0Aconst%20templateArguments%20%3D%20%7B%22bar%22%3A%22BAR%22%2C%20a%3A%201%7D%0A%0Aconst%20result%20%3D%20R.interpolate(inputWithTags%2C%20templateArguments)%0Aconst%20expected%20%3D%20'foo%20is%20BAR%20even%201%20more'%0A%2F%2F%20%3D%3E%20%60result%60%20is%20equal%20to%20%60expected%60\"\u003eTry this \u003cstrong\u003eR.interpolate\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\ninterpolate(inputWithTags: string): (templateArguments: object) =\u003e string;\n\n// API_MARKER_END\n// ============================================\n\nexport as namespace R\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.interpolate\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nconst getOccurrences = input =\u003e input.match(/{{\\s*.+?\\s*}}/g)\nconst getOccurrenceProp = occurrence =\u003e occurrence.replace(/{{\\s*|\\s*}}/g, '')\n\nconst replace = ({ inputHolder, prop, replacer }) =\u003e {\n  const regexBase = `{{${prop}}}`\n  const regex = new RegExp(regexBase, 'g')\n  return inputHolder.replace(regex, replacer)\n}\n\nexport function interpolate(input) {\n  return templateInput =\u003e {\n    const occurrences = getOccurrences(input)\n    if (occurrences === null) {\n      return input\n    }\n    let inputHolder = input\n\n    for (const occurrence of occurrences) {\n      const prop = getOccurrenceProp(occurrence)\n      inputHolder = replace({\n        inputHolder,\n        prop,\n        replacer: templateInput[prop],\n      })\n    }\n\n    return inputHolder\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { interpolate } from './interpolate.js'\nimport { pipe } from './pipe.js'\n\ntest('happy', () =\u003e {\n  const result = pipe(\n\t\t{ name: 'John', age: 30 },\n\t\tinterpolate('My name is {{name}} and I am {{age}} years old')\n\t)\n\texpect(result).toBe('My name is John and I am 30 years old')\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { interpolate } from 'rambda'\n\nconst templateInput = 'foo {{x}} baz'\nconst templateArguments = { x: 'led zeppelin' }\n\nit('R.interpolate', () =\u003e {\n\tconst result = interpolate(templateInput)(templateArguments)\n\n\tresult // $ExpectType string\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#interpolate)\n\n### intersection\n\nIt loops through `listA` and `listB` and returns the intersection of the two according to `R.equals`.\n\n\u003e :boom: There is slight difference between Rambda and Ramda implementation. Ramda.intersection(['a', 'b', 'c'], ['c', 'b']) result is \"[ 'c', 'b' ]\", but Rambda result is \"[ 'b', 'c' ]\".\n\n```javascript\nconst listA = [ { id : 1 }, { id : 2 }, { id : 3 }, { id : 4 } ]\nconst listB = [ { id : 3 }, { id : 4 }, { id : 5 }, { id : 6 } ]\n\nconst result = R.intersection(listA)(listB)\n// =\u003e [{ id : 3 }, { id : 4 }]\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20listA%20%3D%20%5B%20%7B%20id%20%3A%201%20%7D%2C%20%7B%20id%20%3A%202%20%7D%2C%20%7B%20id%20%3A%203%20%7D%2C%20%7B%20id%20%3A%204%20%7D%20%5D%0Aconst%20listB%20%3D%20%5B%20%7B%20id%20%3A%203%20%7D%2C%20%7B%20id%20%3A%204%20%7D%2C%20%7B%20id%20%3A%205%20%7D%2C%20%7B%20id%20%3A%206%20%7D%20%5D%0A%0Aconst%20result%20%3D%20R.intersection(listA)(listB)%0A%2F%2F%20%3D%3E%20%5B%7B%20id%20%3A%203%20%7D%2C%20%7B%20id%20%3A%204%20%7D%5D\"\u003eTry this \u003cstrong\u003eR.intersection\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#intersection)\n\n### intersperse\n\nIt adds a `separator` between members of `list`.\n\n```javascript\nconst list = [ 0, 1, 2, 3 ]\nconst separator = 10\nconst result = R.intersperse(separator)(list)\n// =\u003e [0, 10, 1, 10, 2, 10, 3]\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20list%20%3D%20%5B%200%2C%201%2C%202%2C%203%20%5D%0Aconst%20separator%20%3D%2010%0Aconst%20result%20%3D%20R.intersperse(separator)(list)%0A%2F%2F%20%3D%3E%20%5B0%2C%2010%2C%201%2C%2010%2C%202%2C%2010%2C%203%5D\"\u003eTry this \u003cstrong\u003eR.intersperse\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#intersperse)\n\n### join\n\n```typescript\n\njoin\u003cT\u003e(glue: string): (list: T[]) =\u003e string\n```\n\nIt returns a string of all `list` instances joined with a `glue`.\n\n```javascript\nR.join('-', [1, 2, 3])  // =\u003e '1-2-3'\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20result%20%3D%20R.join('-'%2C%20%5B1%2C%202%2C%203%5D)%20%20%2F%2F%20%3D%3E%20'1-2-3'\"\u003eTry this \u003cstrong\u003eR.join\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\njoin\u003cT\u003e(glue: string): (list: T[]) =\u003e string;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.join\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function join(glue) {\n  return list =\u003e list.join(glue)\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { join, pipe } from 'rambda'\n\nit('R.join', () =\u003e {\n  const result = pipe([1, 2, 3], join('|'))\n  result // $ExpectType string\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#join)\n\n### last\n\n```typescript\n\nlast\u003cT\u003e(listOrString: T): T extends string ? string : \n  T extends [] ? undefined : \n    T extends readonly [...infer R, infer L] ? L : \n      T extends readonly [infer L] ? L :\n        T extends [infer L] ? L :\n          T extends [...infer R, infer L] ? L : \n            T extends unknown[] ? T[number] : \n              undefined\n```\n\nIt returns the last element of `input`, as the `input` can be either a string or an array. It returns `undefined` if array has length of 0.\n\n```javascript\nconst result = [\n  R.last([1, 2, 3]),\n  R.last('foo'),\n]\n// =\u003e [3, 'o']\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20result%20%3D%20%5B%0A%20%20R.last(%5B1%2C%202%2C%203%5D)%2C%0A%20%20R.last('foo')%2C%0A%5D%0A%2F%2F%20%3D%3E%20%5B3%2C%20'o'%5D\"\u003eTry this \u003cstrong\u003eR.last\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nlast\u003cT\u003e(listOrString: T): T extends string ? string : \n  T extends [] ? undefined : \n    T extends readonly [...infer R, infer L] ? L : \n      T extends readonly [infer L] ? L :\n        T extends [infer L] ? L :\n          T extends [...infer R, infer L] ? L : \n            T extends unknown[] ? T[number] : \n              undefined;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.last\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function last(listOrString) {\n  if (typeof listOrString === 'string') {\n    return listOrString[listOrString.length - 1] || ''\n  }\n\n  return listOrString[listOrString.length - 1]\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { last } from './last.js'\n\ntest('with list', () =\u003e {\n  expect(last([1, 2, 3])).toBe(3)\n  expect(last([])).toBeUndefined()\n})\n\ntest('with string', () =\u003e {\n  expect(last('abc')).toBe('c')\n  expect(last('')).toBe('')\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#last)\n\n### lastIndexOf\n\n```typescript\n\nlastIndexOf\u003cT\u003e(target: T): (list: T[]) =\u003e number\n```\n\nIt returns the last index of `target` in `list` array.\n\n`R.equals` is used to determine equality between `target` and members of `list`.\n\nIf there is no such index, then `-1` is returned.\n\n```javascript\nconst list = [1, 2, 3, 1, 2, 3]\nconst result = [\n  R.lastIndexOf(2)(list),\n  R.lastIndexOf(4)(list),\n]\n// =\u003e [4, -1]\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20list%20%3D%20%5B1%2C%202%2C%203%2C%201%2C%202%2C%203%5D%0Aconst%20result%20%3D%20%5B%0A%20%20R.lastIndexOf(2)(list)%2C%0A%20%20R.lastIndexOf(4)(list)%2C%0A%5D%0A%2F%2F%20%3D%3E%20%5B4%2C%20-1%5D\"\u003eTry this \u003cstrong\u003eR.lastIndexOf\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nlastIndexOf\u003cT\u003e(target: T): (list: T[]) =\u003e number;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.lastIndexOf\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nimport { _lastIndexOf } from './equals.js'\n\nexport function lastIndexOf(valueToFind) {\n  return list =\u003e _lastIndexOf(valueToFind, list)\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { lastIndexOf } from './lastIndexOf.js'\n\ntest('with NaN', () =\u003e {\n  expect(lastIndexOf(Number.NaN)([Number.NaN])).toBe(0)\n})\n\ntest('will throw with bad input', () =\u003e {\n  expect(() =\u003e indexOf([])(true)).toThrowError('indexOf is not defined')\n})\n\ntest('without list of objects - no R.equals', () =\u003e {\n  expect(lastIndexOf(3)([1, 2, 3, 4])).toBe(2)\n  expect(lastIndexOf(10)([1, 2, 3, 4])).toBe(-1)\n})\n\ntest('list of objects uses R.equals', () =\u003e {\n  const listOfObjects = [{ a: 1 }, { b: 2 }, { c: 3 }]\n  expect(lastIndexOf({ c: 4 })(listOfObjects)).toBe(-1)\n  expect(lastIndexOf({ c: 3 })(listOfObjects)).toBe(2)\n})\n\ntest('list of arrays uses R.equals', () =\u003e {\n  const listOfLists = [[1], [2, 3], [2, 3, 4], [2, 3], [1], []]\n  expect(lastIndexOf([])(listOfLists)).toBe(5)\n  expect(lastIndexOf([1])(listOfLists)).toBe(4)\n  expect(lastIndexOf([2, 3, 4])(listOfLists)).toBe(2)\n  expect(lastIndexOf([2, 3, 5])(listOfLists)).toBe(-1)\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { lastIndexOf, pipe } from 'rambda'\n\ndescribe('R.lastIndexOf', () =\u003e {\n  const result = pipe([{ a: 1 }, { a: 2 }, { a: 3 }], lastIndexOf({ a: 2 }))\n  result // $ExpectType number\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#lastIndexOf)\n\n### map\n\n```typescript\n\nmap\u003cT extends IterableContainer, U\u003e(\n  fn: (value: T[number], index: number) =\u003e U,\n): (data: T) =\u003e Mapped\u003cT, U\u003e\n```\n\nIt returns the result of looping through `iterable` with `fn`.\n\nIt works with both array and object.\n\n```javascript\nconst fn = x =\u003e x * 2\n\nconst iterable = [1, 2]\nconst obj = {a: 1, b: 2}\n\nconst result = R.map(fn)(iterable),\n// =\u003e [2, 4]\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20fn%20%3D%20x%20%3D%3E%20x%20*%202%0A%0Aconst%20iterable%20%3D%20%5B1%2C%202%5D%0Aconst%20obj%20%3D%20%7Ba%3A%201%2C%20b%3A%202%7D%0A%0Aconst%20result%20%3D%20R.map(fn)(iterable)%2C%0A%2F%2F%20%3D%3E%20%5B2%2C%204%5D\"\u003eTry this \u003cstrong\u003eR.map\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nmap\u003cT extends IterableContainer, U\u003e(\n  fn: (value: T[number], index: number) =\u003e U,\n): (data: T) =\u003e Mapped\u003cT, U\u003e;\nmap\u003cT extends IterableContainer, U\u003e(\n  fn: (value: T[number]) =\u003e U,\n): (data: T) =\u003e Mapped\u003cT, U\u003e;\nmap\u003cT extends IterableContainer, U\u003e(\n  fn: (value: T[number], index: number) =\u003e U,\n\tdata: T\n) : Mapped\u003cT, U\u003e;\nmap\u003cT extends IterableContainer, U\u003e(\n  fn: (value: T[number]) =\u003e U,\n\tdata: T\n) : Mapped\u003cT, U\u003e;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.map\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function map(fn) {\n  return list =\u003e {\n    let index = 0\n    const willReturn = Array(list.length)\n    while (index \u003c list.length) {\n      willReturn[index] = fn(list[index], index)\n      index++\n    }\n    return willReturn\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { map } from './map.js'\n\nconst double = x =\u003e x * 2\n\nit('happy', () =\u003e {\n  expect(map(double)([1, 2, 3])).toEqual([2, 4, 6])\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { map, pipe } from 'rambda'\n\nconst list = [1, 2, 3]\n\nit('R.map', () =\u003e {\n  const result = pipe(\n    list,\n    x =\u003e x,\n    map(x =\u003e {\n      x // $ExpectType number\n      return String(x)\n    }),\n  )\n  result // $ExpectType string[]\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#map)\n\n### mapAsync\n\n```typescript\n\nmapAsync\u003cT extends IterableContainer, U\u003e(\n  fn: (value: T[number], index: number) =\u003e Promise\u003cU\u003e,\n): (data: T) =\u003e Promise\u003cMapped\u003cT, U\u003e\u003e\n```\n\nSequential asynchronous mapping with `fn` over members of `list`.\n\n```javascript\nasync function fn(x){\n  await R.delay(1000)\n\n  return x+1\n}\n\nconst result = await R.mapAsync(fn)([1, 2, 3])\n// `result` resolves after 3 seconds to `[2, 3, 4]`\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?async%20function%20fn(x)%7B%0A%20%20await%20R.delay(1000)%0A%0A%20%20return%20x%2B1%0A%7D%0A%0Aconst%20result%20%3D%20await%20R.mapAsync(fn)(%5B1%2C%202%2C%203%5D)%0A%2F%2F%20%60result%60%20resolves%20after%203%20seconds%20to%20%60%5B2%2C%203%2C%204%5D%60\"\u003eTry this \u003cstrong\u003eR.mapAsync\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nmapAsync\u003cT extends IterableContainer, U\u003e(\n  fn: (value: T[number], index: number) =\u003e Promise\u003cU\u003e,\n): (data: T) =\u003e Promise\u003cMapped\u003cT, U\u003e\u003e;\nmapAsync\u003cT extends IterableContainer, U\u003e(\n  fn: (value: T[number]) =\u003e Promise\u003cU\u003e,\n): (data: T) =\u003e Promise\u003cMapped\u003cT, U\u003e\u003e;\nmapAsync\u003cT extends IterableContainer, U\u003e(\n  fn: (value: T[number], index: number) =\u003e Promise\u003cU\u003e,\n  data: T\n): Promise\u003cMapped\u003cT, U\u003e\u003e;\nmapAsync\u003cT extends IterableContainer, U\u003e(\n  fn: (value: T[number]) =\u003e Promise\u003cU\u003e,\n  data: T\n): Promise\u003cMapped\u003cT, U\u003e\u003e;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.mapAsync\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function mapAsync(fn) {\n  return async list =\u003e {\n    const willReturn = []\n    let i = 0\n    for (const a of list) {\n      willReturn.push(await fn(a, i++))\n    }\n\n    return willReturn\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { delay } from './delay.js'\nimport { map } from './map.js'\nimport { mapAsync } from './mapAsync.js'\nimport { pipeAsync } from './pipeAsync.js'\n\nconst rejectDelay = a =\u003e\n  new Promise((_, reject) =\u003e {\n    setTimeout(() =\u003e {\n      reject(a + 20)\n    }, 100)\n  })\n\ntest('happy', async () =\u003e {\n  const indexes = []\n  const fn = async (x, prop) =\u003e {\n    await delay(100)\n    indexes.push(prop)\n    return x + 1\n  }\n  const result = await mapAsync(fn)([1, 2, 3])\n  expect(result).toEqual([2, 3, 4])\n  expect(indexes).toEqual([0, 1, 2])\n})\n\ntest('with R.pipeAsync', async () =\u003e {\n\tconst fn = async x =\u003e x + 1\n  const result = await pipeAsync(\n    [1, 2, 3],\n    map(x =\u003e x + 1),\n    mapAsync(async x =\u003e {\n      delay(x)\n\n      return x\n    }),\n\t\tmapAsync(fn),\n    map(x =\u003e x * 10),\n  )\n  expect(result).toEqual([30, 40, 50])\n})\n\ntest('error', async () =\u003e {\n  try {\n    await mapAsync(rejectDelay)([1, 2, 3])\n  } catch (err) {\n    expect(err).toBe(21)\n  }\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { mapAsync, pipeAsync } from 'rambda'\nimport { delay } from 'rambdax'\n\nconst list = ['a', 'bc', 'def']\n\nit('R.mapAsync', async () =\u003e {\n\tconst fn = async (x:unknown) =\u003e x as number + 1\n\n  const result = await pipeAsync(\n    list,\n    mapAsync(async x =\u003e {\n      await delay(100)\n      x // $ExpectType string\n      return x.length % 2 ? x.length + 1 : x.length + 10\n    }),\n    x =\u003e x,\n\t\tmapAsync(fn),\n    mapAsync(async x =\u003e {\n      await delay(100)\n      return x + 1\n    }),\n  )\n  result // $ExpectType number[]\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#mapAsync)\n\n### mapKeys\n\n```typescript\n\nmapKeys\u003cT\u003e(fn: (prop: string, value: T) =\u003e string): (obj: Record\u003cstring, T\u003e) =\u003e Record\u003cstring, T\u003e\n```\n\nIt returns a copy of `obj` with keys transformed by `fn`.\n\n```javascript\nconst result = R.mapKeys(\n\t(key, value) =\u003e key.toUpperCase()+value\n\t)(\n\t{ a: 1, b: 2 }\n)\n// =\u003e { A1: 1, B2: 2 }\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20result%20%3D%20R.mapKeys(%0A%09(key%2C%20value)%20%3D%3E%20key.toUpperCase()%2Bvalue%0A%09)(%0A%09%7B%20a%3A%201%2C%20b%3A%202%20%7D%0A)%0A%2F%2F%20%3D%3E%20%7B%20A1%3A%201%2C%20B2%3A%202%20%7D\"\u003eTry this \u003cstrong\u003eR.mapKeys\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nmapKeys\u003cT\u003e(fn: (prop: string, value: T) =\u003e string): (obj: Record\u003cstring, T\u003e) =\u003e Record\u003cstring, T\u003e;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.mapKeys\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function mapKeys(fn) {\n  return obj =\u003e {\n\t\tconst willReturn = {}\n\n\t\tObject.keys(obj).forEach(key =\u003e {\n\t\t\twillReturn[fn(key, obj[key])] = obj[key]\n\t\t})\n\n\t\treturn willReturn\n\t}\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { mapKeys } from \"./mapKeys.js\"\n\ntest('happy', () =\u003e {\n\tconst result = mapKeys((prop, x) =\u003e `${ prop }-${x}`)({a:1, b: 2 })\n\tconst expected = { 'a-1': 1, 'b-2': 2 }\n\n\texpect(result).toEqual(expected)\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { mapKeys, pipe } from 'rambda'\n\nit('R.mapKeys', () =\u003e {\n  const result = pipe(\n    { a: 1, b: 2 },\n    mapKeys((prop, x) =\u003e `${prop}-${x}`),\n    mapKeys(prop =\u003e `${prop}-${prop}`),\n  )\n  result // $ExpectType Record\u003cstring, number\u003e\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#mapKeys)\n\n### mapObject\n\n```typescript\n\nmapObject\u003cT extends object, Value\u003e(\n  valueMapper: (\n    value: EnumerableStringKeyedValueOf\u003cT\u003e,\n    key: EnumerableStringKeyOf\u003cT\u003e,\n    data: T,\n  ) =\u003e Value,\n): (data: T) =\u003e MappedValues\u003cT, Value\u003e\n```\n\n```javascript\nconst fn = (val, prop) =\u003e `${prop}-${val}`\nconst obj = {a: 1, b: 2}\n\nconst result = R.mapObject(fn)(obj)\n// =\u003e {a: 'a-1', b: 'b-2'}\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20fn%20%3D%20(val%2C%20prop)%20%3D%3E%20%60%24%7Bprop%7D-%24%7Bval%7D%60%0Aconst%20obj%20%3D%20%7Ba%3A%201%2C%20b%3A%202%7D%0A%0Aconst%20result%20%3D%20R.mapObject(fn)(obj)%0A%2F%2F%20%3D%3E%20%7Ba%3A%20'a-1'%2C%20b%3A%20'b-2'%7D\"\u003eTry this \u003cstrong\u003eR.mapObject\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nmapObject\u003cT extends object, Value\u003e(\n  valueMapper: (\n    value: EnumerableStringKeyedValueOf\u003cT\u003e,\n    key: EnumerableStringKeyOf\u003cT\u003e,\n    data: T,\n  ) =\u003e Value,\n): (data: T) =\u003e MappedValues\u003cT, Value\u003e;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.mapObject\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nimport { keys } from './_internals/keys.js'\n\nexport function mapObject(fn) {\n  return obj =\u003e {\n    let index = 0\n    const objKeys = keys(obj)\n    const len = objKeys.length\n    const willReturn = {}\n\n    while (index \u003c len) {\n      const key = objKeys[index]\n      willReturn[key] = fn(obj[key], key, obj)\n      index++\n    }\n\n    return willReturn\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { mapObject } from './mapObject.js'\n\nconst double = x =\u003e x * 2\n\nit('happy', () =\u003e {\n  expect(mapObject(double)({ a: 1, b: 2, c: 3 })).toEqual({ a: 2, b: 4, c: 6 })\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { mapObject, pipe } from 'rambda'\n\ndescribe('R.mapObject', () =\u003e {\n  it('iterable with one arguments', () =\u003e {\n    const result = pipe(\n      { a: 1 },\n      mapObject(a =\u003e {\n        a // $ExpectType number\n        return `${a}`\n      }),\n    )\n\n    result // $ExpectType { a: string; }\n  })\n  it('iterable with two three arguments', () =\u003e {\n    const result = pipe(\n      { a: 1, b: 'foo' },\n      mapObject((a, b) =\u003e {\n        a // $ExpectType string | number\n        b // $ExpectType \"a\" | \"b\"\n        return `${a}`\n      }),\n    )\n\n    result // $ExpectType { a: string; b: string; }\n  })\n  it('iterable with three arguments', () =\u003e {\n    const result = pipe(\n      { a: 1, b: 'foo' },\n      mapObject((a, b, c) =\u003e {\n        a // $ExpectType string | number\n        b // $ExpectType \"a\" | \"b\"\n        c // $ExpectType { a: number; b: string; }\n        return `${a}`\n      }),\n    )\n\n    result // $ExpectType { a: string; b: string; }\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#mapObject)\n\n### mapObjectAsync\n\n```typescript\n\nmapObjectAsync\u003cT extends object, Value\u003e(\n  valueMapper: (\n    value: EnumerableStringKeyedValueOf\u003cT\u003e,\n    key: EnumerableStringKeyOf\u003cT\u003e,\n    data: T,\n  ) =\u003e Promise\u003cValue\u003e,\n): (data: T) =\u003e Promise\u003cMappedValues\u003cT, Value\u003e\u003e\n```\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nmapObjectAsync\u003cT extends object, Value\u003e(\n  valueMapper: (\n    value: EnumerableStringKeyedValueOf\u003cT\u003e,\n    key: EnumerableStringKeyOf\u003cT\u003e,\n    data: T,\n  ) =\u003e Promise\u003cValue\u003e,\n): (data: T) =\u003e Promise\u003cMappedValues\u003cT, Value\u003e\u003e;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.mapObjectAsync\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function mapObjectAsync(fn) {\n  return async obj =\u003e {\n    const willReturn = {}\n    for (const prop in obj) {\n      willReturn[prop] = await fn(obj[prop], prop)\n    }\n\n    return willReturn\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { delay } from './delay.js'\nimport { mapObjectAsync } from './mapObjectAsync.js'\nimport { pipeAsync } from './pipeAsync.js'\n\ntest('happy', async () =\u003e {\n  const indexes = []\n  const result = await pipeAsync(\n    { a: 1, b: 2 },\n    mapObjectAsync(async (x, i) =\u003e {\n      await delay(100)\n      indexes.push(i)\n      return x + 1\n    }),\n  )\n  expect(indexes).toEqual(['a', 'b'])\n  expect(result).toEqual({\n    a: 2,\n    b: 3,\n  })\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { mapObjectAsync, pipeAsync } from 'rambda'\nimport { delay } from 'rambdax'\n\nit('R.mapObjectAsync', async () =\u003e {\n  const result = await pipeAsync(\n    { a: 'foo', b: 'bar' },\n    mapObjectAsync(async x =\u003e {\n      await delay(100)\n      x // $ExpectType string\n      return x.length % 2 ? x.length + 1 : x.length + 10\n    }),\n    x =\u003e x,\n    mapObjectAsync(async x =\u003e {\n      await delay(100)\n      return x + 1\n    }),\n  )\n  result.a // $ExpectType number\n  result.b // $ExpectType number\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#mapObjectAsync)\n\n### mapParallelAsync\n\n```typescript\n\nmapParallelAsync\u003cT extends IterableContainer, U\u003e(\n  fn: (value: T[number], index: number) =\u003e Promise\u003cU\u003e,\n): (data: T) =\u003e Promise\u003cMapped\u003cT, U\u003e\u003e\n```\n\nWrapper around `Promise.all` for asynchronous mapping with `fn` over members of `list`.\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nmapParallelAsync\u003cT extends IterableContainer, U\u003e(\n  fn: (value: T[number], index: number) =\u003e Promise\u003cU\u003e,\n): (data: T) =\u003e Promise\u003cMapped\u003cT, U\u003e\u003e;\nmapParallelAsync\u003cT extends IterableContainer, U\u003e(\n  fn: (value: T[number]) =\u003e Promise\u003cU\u003e,\n): (data: T) =\u003e Promise\u003cMapped\u003cT, U\u003e\u003e;\nmapParallelAsync\u003cT extends IterableContainer, U\u003e(\n  fn: (value: T[number], index: number) =\u003e Promise\u003cU\u003e,\n  data: T\n): Promise\u003cMapped\u003cT, U\u003e\u003e;\nmapParallelAsync\u003cT extends IterableContainer, U\u003e(\n  fn: (value: T[number]) =\u003e Promise\u003cU\u003e,\n  data: T\n): Promise\u003cMapped\u003cT, U\u003e\u003e;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.mapParallelAsync\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function mapParallelAsync(fn) {\n  return async list =\u003e  Promise.all(list.map((x, i) =\u003e fn(x, i)))\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { pipeAsync } from './pipeAsync.js'\nimport { delay } from './delay.js'\nimport { mapParallelAsync } from './mapParallelAsync.js'\n\ntest('happy', async () =\u003e {\n  const fn = async (x, i) =\u003e {\n    await delay(100)\n\n    return x + i\n  }\n  const result = await mapParallelAsync(fn)([ 1, 2, 3 ])\n  expect(result).toEqual([ 1, 3, 5 ])\n})\n\ntest('pipeAsync', async () =\u003e {\n  const result = await pipeAsync(\n\t\t[1, 2, 3],\n    mapParallelAsync(async x =\u003e {\n      await delay(100)\n\n      return x + 1\n    })\n\t)\n  expect(result).toEqual([ 2,3,4 ])\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#mapParallelAsync)\n\n### match\n\n```typescript\n\nmatch(regExpression: RegExp): (str: string) =\u003e string[]\n```\n\nCurried version of `String.prototype.match` which returns empty array, when there is no match.\n\n```javascript\nconst result = [\n  R.match('a', 'foo'),\n  R.match(/([a-z]a)/g, 'bananas')\n]\n// =\u003e [[], ['ba', 'na', 'na']]\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20result%20%3D%20%5B%0A%20%20R.match('a'%2C%20'foo')%2C%0A%20%20R.match(%2F(%5Ba-z%5Da)%2Fg%2C%20'bananas')%0A%5D%0A%2F%2F%20%3D%3E%20%5B%5B%5D%2C%20%5B'ba'%2C%20'na'%2C%20'na'%5D%5D\"\u003eTry this \u003cstrong\u003eR.match\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nmatch(regExpression: RegExp): (str: string) =\u003e string[];\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.match\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function match(pattern) {\n  return input =\u003e {\n    const willReturn = input.match(pattern)\n\n    return willReturn === null ? [] : willReturn\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { match } from './match.js'\n\ntest('happy', () =\u003e {\n  expect(match(/a./g)('foo bar baz')).toEqual(['ar', 'az'])\n})\n\ntest('fallback', () =\u003e {\n  expect(match(/a./g)('foo')).toEqual([])\n})\n\ntest('with string', () =\u003e {\n  expect(match('a')('foo')).toEqual([])\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { match } from 'rambda'\n\nconst str = 'foo bar'\n\ndescribe('R.match', () =\u003e {\n  it('happy', () =\u003e {\n    const result = match(/foo/)(str)\n    result // $ExpectType string[]\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#match)\n\n### maxBy\n\nIt returns the greater value between `x` and `y` according to `compareFn` function.\n\n```javascript\nconst compareFn = Math.abs\n\nR.maxBy(compareFn, 5, -7) // =\u003e -7\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20compareFn%20%3D%20Math.abs%0A%0Aconst%20result%20%3D%20R.maxBy(compareFn%2C%205%2C%20-7)%20%2F%2F%20%3D%3E%20-7\"\u003eTry this \u003cstrong\u003eR.maxBy\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#maxBy)\n\n### merge\n\nIt creates a copy of `target` object with overwritten `newProps` properties.\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#merge)\n\n### mergeTypes\n\n```typescript\n\nmergeTypes\u003cT\u003e(x: T): MergeTypes\u003cT\u003e\n```\n\nHelper to merge all calculated TypeScript definitions into one definition.\nIt returns its input and it is intended to be used as last method inside `R.pipe` chain.\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nmergeTypes\u003cT\u003e(x: T): MergeTypes\u003cT\u003e;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.mergeTypes\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function mergeTypes(x) {\n  return x\n}\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#mergeTypes)\n\n### minBy\n\nIt returns the lesser value between `x` and `y` according to `compareFn` function.\n\n```javascript\nconst compareFn = Math.abs\n\nR.minBy(compareFn, -5, 2) // =\u003e -5\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20compareFn%20%3D%20Math.abs%0A%0Aconst%20result%20%3D%20R.minBy(compareFn%2C%20-5%2C%202)%20%2F%2F%20%3D%3E%20-5\"\u003eTry this \u003cstrong\u003eR.minBy\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#minBy)\n\n### modifyProp\n\n```typescript\n\nmodifyProp\u003cT, K extends keyof T\u003e(\n  prop: K,\n  fn: (x: T[K]) =\u003e T[K],\n): (target: T) =\u003e T\n```\n\nIt changes a property with the result of transformer function.\n\n```javascript\nconst person = {\n  name : 'foo',\n  age  : 20,\n}\nconst result = R.modifyProp('age', x =\u003e x + 1)(person) \n// =\u003e {name: 'foo', age: 21}\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20person%20%3D%20%7B%0A%20%20name%20%3A%20'foo'%2C%0A%20%20age%20%20%3A%2020%2C%0A%7D%0Aconst%20result%20%3D%20R.modifyProp('age'%2C%20x%20%3D%3E%20x%20%2B%201)(person)%20%0A%2F%2F%20%3D%3E%20%7Bname%3A%20'foo'%2C%20age%3A%2021%7D\"\u003eTry this \u003cstrong\u003eR.modifyProp\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nmodifyProp\u003cT, K extends keyof T\u003e(\n  prop: K,\n  fn: (x: T[K]) =\u003e T[K],\n): (target: T) =\u003e T;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.modifyProp\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nimport { isArray } from './_internals/isArray.js'\nimport { update } from './update.js'\n\nfunction modifyFn(property, fn, list) {\n  if (list[property] === undefined) {\n    return list\n  }\n  if (isArray(list)) {\n    return update(property, fn(list[property]))(list)\n  }\n\n  return {\n    ...list,\n    [property]: fn(list[property]),\n  }\n}\n\nexport function modifyProp(property, fn) {\n  return obj =\u003e modifyFn(property, fn, obj)\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { modifyProp } from './modifyProp.js'\n\nconst person = {\n  name: 'foo',\n  age: 20,\n}\n\ntest('happy', () =\u003e {\n  expect(modifyProp('age', x =\u003e x + 1)(person)).toEqual({\n    name: 'foo',\n    age: 21,\n  })\n})\n\ntest('property is missing', () =\u003e {\n  expect(modifyProp('foo', x =\u003e x + 1)(person)).toEqual(person)\n})\n\ntest('adjust if `array` at the given key with the `transformation` function', () =\u003e {\n  expect(modifyProp(1, x =\u003e x + 1)([100, 1400])).toEqual([100, 1401])\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { modifyProp, pipe } from 'rambda'\n\nit('R.modify', () =\u003e {\n  const result = pipe(\n    { a: 1, b: 2, c: { d: 3 } },\n    modifyProp('a', val =\u003e val + 1),\n  )\n  result // $ExpectType { a: number; b: number; c: { d: number; }; }\n\n  pipe(\n    { a: 1, b: 2, c: { d: 3 } },\n    // @ts-expect-error\n    modifyProp('ax', val =\u003e val + 1),\n  )\n\n  pipe(\n    { a: 1, b: 2, c: { d: 3 } },\n    // @ts-expect-error\n    modifyProp('a', val =\u003e String(val)),\n  )\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#modifyProp)\n\n### none\n\n```typescript\n\nnone\u003cT\u003e(predicate: (x: T) =\u003e boolean): (list: T[]) =\u003e boolean\n```\n\nIt returns `true`, if all members of array `list` returns `false`, when applied as argument to `predicate` function.\n\n```javascript\nconst list = [ 0, 1, 2, 3, 4 ]\nconst predicate = x =\u003e x \u003e 6\n\nconst result = R.none(predicate)(arr)\n// =\u003e true\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20list%20%3D%20%5B%200%2C%201%2C%202%2C%203%2C%204%20%5D%0Aconst%20predicate%20%3D%20x%20%3D%3E%20x%20%3E%206%0A%0Aconst%20result%20%3D%20R.none(predicate)(arr)%0A%2F%2F%20%3D%3E%20true\"\u003eTry this \u003cstrong\u003eR.none\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nnone\u003cT\u003e(predicate: (x: T) =\u003e boolean): (list: T[]) =\u003e boolean;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.none\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function none(predicate) {\n  return list =\u003e {\n    for (let i = 0; i \u003c list.length; i++) {\n      if (predicate(list[i])) {\n        return false\n      }\n    }\n\n    return true\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { none } from './none.js'\n\nconst isEven = n =\u003e n % 2 === 0\n\ntest('when true', () =\u003e {\n  expect(none(isEven)([1, 3, 5, 7])).toBeTruthy()\n})\n\ntest('when false', () =\u003e {\n  expect(none(input =\u003e input \u003e 1)([1, 2, 3])).toBeFalsy()\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { none, pipe } from 'rambda'\n\ndescribe('R.none', () =\u003e {\n  it('happy', () =\u003e {\n    const result = pipe(\n      [1, 2, 3],\n      none(x =\u003e x \u003e 0),\n    )\n    result // $ExpectType boolean\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#none)\n\n### objectIncludes\n\n```typescript\n\nobjectIncludes\u003cT\u003e(specification: T): (obj: Partial\u003cT\u003e) =\u003e boolean\n```\n\nIt will return `true` if `specification` object fully or partially include `obj` object.\n\n`R.equals` is used to determine equality.\n\n```javascript\nconst specification = { a : { b : 1 } }\nconst input = {\n  a : { b : 1 },\n  c : 2\n}\n\nconst result = objectIncludes(specification)(input)\n// =\u003e true\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20specification%20%3D%20%7B%20a%20%3A%20%7B%20b%20%3A%201%20%7D%20%7D%0Aconst%20input%20%3D%20%7B%0A%20%20a%20%3A%20%7B%20b%20%3A%201%20%7D%2C%0A%20%20c%20%3A%202%0A%7D%0A%0Aconst%20result%20%3D%20objectIncludes(specification)(input)%0A%2F%2F%20%3D%3E%20true\"\u003eTry this \u003cstrong\u003eR.objectIncludes\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nobjectIncludes\u003cT\u003e(specification: T): (obj: Partial\u003cT\u003e) =\u003e boolean;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.objectIncludes\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nimport { equals } from './equals.js'\nimport { filterObject } from './filterObject.js'\n\nexport function objectIncludes(condition) {\n  return obj =\u003e {\n    const result = filterObject((conditionValue, conditionProp) =\u003e\n      equals(conditionValue)(obj[conditionProp]),\n    )(condition)\n\n    return Object.keys(result).length === Object.keys(condition).length\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { objectIncludes } from './objectIncludes.js'\n\ntest('when true', () =\u003e {\n  const condition = { a: 1 }\n  const input = {\n    a: 1,\n    b: 2,\n  }\n\n  const result = objectIncludes(condition)(input)\n  const expectedResult = true\n\n  expect(result).toEqual(expectedResult)\n})\n\ntest('when false', () =\u003e {\n  const condition = { a: 1 }\n  const input = { b: 2 }\n\n  const result = objectIncludes(condition)(input)\n  const expectedResult = false\n\n  expect(result).toEqual(expectedResult)\n})\n\ntest('with nested object', () =\u003e {\n  const condition = { a: { b: 1 } }\n  const input = {\n    a: { b: 1 },\n    c: 2,\n  }\n\n  const result = objectIncludes(condition)(input)\n  const expectedResult = true\n\n  expect(result).toEqual(expectedResult)\n})\n\ntest('with wrong input', () =\u003e {\n  const condition = { a: { b: 1 } }\n\n  expect(() =\u003e objectIncludes(condition)(null)).toThrowErrorMatchingInlineSnapshot(\n    `[TypeError: Cannot read properties of null (reading 'a')]`,\n  )\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { objectIncludes, pipe } from 'rambda'\n\ndescribe('R.objectIncludes', () =\u003e {\n  it('happy', () =\u003e {\n    const result = pipe({ a: 1, b: 2, c: { d: 3 } }, objectIncludes({ a: 2 }))\n    result // $ExpectType boolean\n  })\n  it('nested', () =\u003e {\n    const result = pipe({ a: 1, b: 2, c: { d: 3 } }, objectIncludes({ c: { d: 3 } }))\n    result // $ExpectType boolean\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#objectIncludes)\n\n### objOf\n\nIt creates an object with a single key-value pair.\n\n```javascript\nconst result = R.objOf('foo')('bar')\n// =\u003e {foo: 'bar'}\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20result%20%3D%20R.objOf('foo')('bar')%0A%2F%2F%20%3D%3E%20%7Bfoo%3A%20'bar'%7D\"\u003eTry this \u003cstrong\u003eR.objOf\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#objOf)\n\n### omit\n\n```typescript\n\nomit\u003c\n\tS extends string,\n\tKeys extends PickStringToPickPath\u003cS\u003e,\n\u003e(propsToPick: S): \u003cU extends Partial\u003cRecord\u003cElementOf\u003cKeys\u003e, any\u003e\u003e\u003e(\n\tobj: ElementOf\u003cKeys\u003e extends keyof U ? U : never\n) =\u003e ElementOf\u003cKeys\u003e extends keyof U ? MergeTypes\u003cOmit\u003cU, ElementOf\u003cKeys\u003e\u003e\u003e : never\n```\n\nIt returns a partial copy of an `obj` without `propsToOmit` properties.\n\n```javascript\nconst obj = {a: 1, b: 2, c: 3}\nconst propsToOmit = 'a,c,d'\nconst propsToOmitList = ['a', 'c', 'd']\n\nconst result = [\n  R.omit(propsToOmit, obj), \n  R.omit(propsToOmitList, obj) \n]\n// =\u003e [{b: 2}, {b: 2}]\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20obj%20%3D%20%7Ba%3A%201%2C%20b%3A%202%2C%20c%3A%203%7D%0Aconst%20propsToOmit%20%3D%20'a%2Cc%2Cd'%0Aconst%20propsToOmitList%20%3D%20%5B'a'%2C%20'c'%2C%20'd'%5D%0A%0Aconst%20result%20%3D%20%5B%0A%20%20R.omit(propsToOmit%2C%20obj)%2C%20%0A%20%20R.omit(propsToOmitList%2C%20obj)%20%0A%5D%0A%2F%2F%20%3D%3E%20%5B%7Bb%3A%202%7D%2C%20%7Bb%3A%202%7D%5D\"\u003eTry this \u003cstrong\u003eR.omit\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nomit\u003c\n\tS extends string,\n\tKeys extends PickStringToPickPath\u003cS\u003e,\n\u003e(propsToPick: S): \u003cU extends Partial\u003cRecord\u003cElementOf\u003cKeys\u003e, any\u003e\u003e\u003e(\n\tobj: ElementOf\u003cKeys\u003e extends keyof U ? U : never\n) =\u003e ElementOf\u003cKeys\u003e extends keyof U ? MergeTypes\u003cOmit\u003cU, ElementOf\u003cKeys\u003e\u003e\u003e : never;\nomit\u003cconst Keys extends PropertyKey[]\u003e(propsToPick: Keys): \u003c\n\tU extends Partial\u003cRecord\u003cElementOf\u003cKeys\u003e, any\u003e\u003e\n\u003e(\n\tobj: ElementOf\u003cKeys\u003e extends keyof U ? U : never\n) =\u003e ElementOf\u003cKeys\u003e extends keyof U ? MergeTypes\u003cOmit\u003cU, ElementOf\u003cKeys\u003e\u003e\u003e : never;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.omit\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nimport { createPath } from './_internals/createPath.js'\n\nexport function _includes(x, list) {\n  let index = -1\n  const { length } = list\n\n  while (++index \u003c length) {\n    if (String(list[index]) === String(x)) {\n      return true\n    }\n  }\n\n  return false\n}\n\nexport function omit(propsToOmit) {\n  return obj =\u003e {\n    if (!obj) {\n      return undefined\n    }\n\n    const propsToOmitValue = createPath(propsToOmit, ',')\n    const willReturn = {}\n\n    for (const key in obj) {\n      if (!_includes(key, propsToOmitValue)) {\n        willReturn[key] = obj[key]\n      }\n    }\n\n    return willReturn\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { omit } from './omit.js'\n\ntest('with string as condition', () =\u003e {\n  const obj = {\n    a: 1,\n    b: 2,\n    c: 3,\n  }\n  const result = omit('a,c')(obj)\n  const expectedResult = { b: 2 }\n\n  expect(result).toEqual(expectedResult)\n})\n\ntest('with array as condition', () =\u003e {\n  expect(\n    omit(['a', 'c', 'd'])({\n      a: 'foo',\n      b: 'bar',\n      c: 'baz',\n    }),\n  ).toEqual({ b: 'bar' })\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { omit, pipe } from 'rambda'\n\nconst input = { a: 'foo', b: 2, c: 3 }\n\ndescribe('R.omit', () =\u003e {\n  it('with string as input', () =\u003e {\n    const result = pipe(input, omit('a,b'))\n    result.c // $ExpectType number\n  })\n  it('with array as input', () =\u003e {\n    const result = pipe(input, omit(['a', 'b']))\n    result.c // $ExpectType number\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#omit)\n\n### partition\n\n```typescript\n\npartition\u003cT, S extends T\u003e(\n  predicate: (value: T, index: number, data: ReadonlyArray\u003cT\u003e) =\u003e value is S,\n): (data: ReadonlyArray\u003cT\u003e) =\u003e [Array\u003cS\u003e, Array\u003cExclude\u003cT, S\u003e\u003e]\n```\n\nIt will return array of two arrays according to `predicate` function. The first member holds all instances of `input` that pass the `predicate` function, while the second member - those who doesn't.\n\n```javascript\nconst list = [1, 2, 3]\nconst predicate = x =\u003e x \u003e 2\n\nconst result = R.partition(predicate)(list)\n\nconst expected = [[3], [1, 2]]\n// `result` is equal to `expected`\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20list%20%3D%20%5B1%2C%202%2C%203%5D%0Aconst%20predicate%20%3D%20x%20%3D%3E%20x%20%3E%202%0A%0Aconst%20result%20%3D%20R.partition(predicate)(list)%0A%0Aconst%20expected%20%3D%20%5B%5B3%5D%2C%20%5B1%2C%202%5D%5D%0A%2F%2F%20%60result%60%20is%20equal%20to%20%60expected%60\"\u003eTry this \u003cstrong\u003eR.partition\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\npartition\u003cT, S extends T\u003e(\n  predicate: (value: T, index: number, data: ReadonlyArray\u003cT\u003e) =\u003e value is S,\n): (data: ReadonlyArray\u003cT\u003e) =\u003e [Array\u003cS\u003e, Array\u003cExclude\u003cT, S\u003e\u003e];\npartition\u003cT\u003e(\n  predicate: (value: T, index: number, data: ReadonlyArray\u003cT\u003e) =\u003e boolean,\n): (data: ReadonlyArray\u003cT\u003e) =\u003e [Array\u003cT\u003e, Array\u003cT\u003e];\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.partition\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function partition(predicate) {\n  return list =\u003e {\n\t\tconst yes = []\n\t\tconst no = []\n\t\tlet counter = -1\n\t\n\t\twhile (counter++ \u003c list.length - 1) {\n\t\t\tif (predicate(list[counter], counter)) {\n\t\t\t\tyes.push(list[counter])\n\t\t\t} else {\n\t\t\t\tno.push(list[counter])\n\t\t\t}\n\t\t}\n\t\n\t\treturn [yes, no]\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { partition } from './partition.js'\n\ntest('happy', () =\u003e {\n  const list = [1, 2, 3]\n  const predicate = x =\u003e x \u003e 2\n\n  const result = partition(predicate)(list)\n  expect(result).toEqual([[3], [1, 2]])\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { partition, pipe } from 'rambda'\n\ndescribe('R.partition', () =\u003e {\n  it('happy', () =\u003e {\n    const predicate = (x: number) =\u003e {\n      return x \u003e 2\n    }\n    const list = [1, 2, 3, 4]\n\n    const result = pipe(list, partition(predicate))\n    result // $ExpectType [number[], number[]]\n  })\n  it('with simple object', () =\u003e {\n    const result = pipe(\n      [{ a: 1 }, { a: 2 }, { a: 3 }, { a: 4 }],\n      partition(x =\u003e x.a \u003e 2),\n    )\n    result // $ExpectType [{ a: number; }[], { a: number; }[]]\n  })\n  it('with complex object', () =\u003e {\n    interface Foo {\n      a: number\n    }\n    interface Bar {\n      b: number\n    }\n    const list1: (Foo | Bar)[] = [{ a: 1 }, { b: 2 }, { a: 3 }, { b: 4 }]\n    const filterFoo = (x: Foo | Bar): x is Foo =\u003e 'a' in x\n    const result = pipe(list1, partition(filterFoo))\n    result // $ExpectType [Foo[], Bar[]]\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#partition)\n\n### partitionObject\n\n```typescript\n\npartitionObject\u003cT extends unknown, S extends T\u003e(\n  predicate: (value: T, prop: string, obj: Record\u003cstring, T\u003e) =\u003e value is S,\n): (obj: Record\u003cstring, T\u003e) =\u003e [Record\u003cstring, S\u003e, Record\u003cstring, Exclude\u003cT, S\u003e\u003e]\n```\n\nIt returns an array containing two objects. The first object holds all properties of the input object for which the predicate returns true, while the second object holds those that do not.\n\n```javascript\nconst obj = {a: 1, b: 2, c: 3}\nconst predicate = x =\u003e x \u003e 2\n\nconst result = R.partition(predicate)(obj)\n\nconst expected = [{c: 3},  {a: 1, b: 2}]\n// `result` is equal to `expected`\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20obj%20%3D%20%7Ba%3A%201%2C%20b%3A%202%2C%20c%3A%203%7D%0Aconst%20predicate%20%3D%20x%20%3D%3E%20x%20%3E%202%0A%0Aconst%20result%20%3D%20R.partition(predicate)(obj)%0A%0Aconst%20expected%20%3D%20%5B%7Bc%3A%203%7D%2C%20%20%7Ba%3A%201%2C%20b%3A%202%7D%5D%0A%2F%2F%20%60result%60%20is%20equal%20to%20%60expected%60\"\u003eTry this \u003cstrong\u003eR.partitionObject\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\npartitionObject\u003cT extends unknown, S extends T\u003e(\n  predicate: (value: T, prop: string, obj: Record\u003cstring, T\u003e) =\u003e value is S,\n): (obj: Record\u003cstring, T\u003e) =\u003e [Record\u003cstring, S\u003e, Record\u003cstring, Exclude\u003cT, S\u003e\u003e];\npartitionObject\u003cT extends unknown\u003e(\n  predicate: (value: T, prop: string, obj: Record\u003cstring, T\u003e) =\u003e boolean,\n): (obj: Record\u003cstring, T\u003e) =\u003e [Record\u003cstring, T\u003e, Record\u003cstring, T\u003e];\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.partitionObject\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function partitionObject(predicate) {\n\treturn obj =\u003e {\n  const yes = {}\n  const no = {}\n  Object.entries(obj).forEach(([prop, value]) =\u003e {\n    if (predicate(value, prop)) {\n      yes[prop] = value\n    } else {\n      no[prop] = value\n    }\n  })\n\n  return [yes, no]\n}\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { partitionObject } from './partitionObject.js'\n\ntest('happy', () =\u003e {\n  const predicate = (value, prop) =\u003e {\n    expect(typeof prop).toBe('string')\n\n    return value \u003e 2\n  }\n  const hash = {\n    a: 1,\n    b: 2,\n    c: 3,\n    d: 4,\n  }\n\n  const result = partitionObject(predicate)(hash)\n  const expectedResult = [\n    {\n      c: 3,\n      d: 4,\n    },\n    {\n      a: 1,\n      b: 2,\n    },\n  ]\n\n  expect(result).toEqual(expectedResult)\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { partitionObject, pipe } from 'rambda'\n\ndescribe('R.partition', () =\u003e {\n  it('happy', () =\u003e {\n\t\tlet result = pipe(\n\t\t\t{ a: 1, b: 2 },\n\t\t\tpartitionObject((x, prop) =\u003e x\u003e 1 || prop === 'c'),\n\t\t)\n    result // $ExpectType [Record\u003cstring, number\u003e, Record\u003cstring, number\u003e]\n  })\n  it('with complex object', () =\u003e {\n    interface Foo {\n      a: number\n    }\n    interface Bar {\n      b: number\n    }\n    const obj: Record\u003cstring, (Foo | Bar)\u003e = {\n\t\t\ta: { a: 1 },\n\t\t\tb: { b: 2 },\n\t\t\tc: { a: 3 },\n\t\t\td: { b: 4 },\n\t\t}\n    const filterFoo = (x: Foo | Bar): x is Foo =\u003e 'a' in x\n    const result = pipe(obj, partitionObject(filterFoo))\n    result // $ExpectType [Record\u003cstring, Foo\u003e, Record\u003cstring, Bar\u003e]\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#partitionObject)\n\n### path\n\n```typescript\n\npath\u003cS, K0 extends string \u0026 keyof S\u003e(path: `${K0}`): (obj: S) =\u003e S[K0]\n```\n\nIf `pathToSearch` is `'a.b'` then it will return `1` if `obj` is `{a:{b:1}}`.\n\nIt will return `undefined`, if such path is not found.\n\n\u003e :boom: String annotation of `pathToSearch` is one of the differences between `Rambda` and `Ramda`.\n\n```javascript\nconst obj = {a: {b: 1}}\nconst pathToSearch = 'a.b'\nconst pathToSearchList = ['a', 'b']\n\nconst result = [\n  R.path(pathToSearch, obj),\n  R.path(pathToSearchList, obj),\n  R.path('a.b.c.d', obj)\n]\n// =\u003e [1, 1, undefined]\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20obj%20%3D%20%7Ba%3A%20%7Bb%3A%201%7D%7D%0Aconst%20pathToSearch%20%3D%20'a.b'%0Aconst%20pathToSearchList%20%3D%20%5B'a'%2C%20'b'%5D%0A%0Aconst%20result%20%3D%20%5B%0A%20%20R.path(pathToSearch%2C%20obj)%2C%0A%20%20R.path(pathToSearchList%2C%20obj)%2C%0A%20%20R.path('a.b.c.d'%2C%20obj)%0A%5D%0A%2F%2F%20%3D%3E%20%5B1%2C%201%2C%20undefined%5D\"\u003eTry this \u003cstrong\u003eR.path\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\npath\u003cS, K0 extends string \u0026 keyof S\u003e(path: `${K0}`): (obj: S) =\u003e S[K0];\npath\u003cS, K0 extends string \u0026 keyof S, K1 extends string \u0026 keyof S[K0]\u003e(path: `${K0}.${K1}`): (obj: S) =\u003e S[K0][K1];\npath\u003c\n  S,\n  K0 extends keyof S,\n  K1 extends keyof S[K0],\n  K2 extends keyof S[K0][K1]\n\u003e(path: [K0, K1, K2]): (obj: S) =\u003e S[K0][K1][K2];\npath\u003c\n  S,\n  K0 extends string \u0026 keyof S,\n  K1 extends string \u0026 keyof S[K0],\n  K2 extends string \u0026 keyof S[K0][K1]\n\u003e(path: `${K0}.${K1}.${K2}`): (obj: S) =\u003e S[K0][K1][K2];\npath\u003c\n  S,\n  K0 extends keyof S,\n  K1 extends keyof S[K0],\n  K2 extends keyof S[K0][K1],\n  K3 extends keyof S[K0][K1][K2]\n\u003e(path: [K0, K1, K2, K3]): (obj: S) =\u003e S[K0][K1][K2][K3];\npath\u003c\n  S,\n  K0 extends string \u0026 keyof S,\n  K1 extends string \u0026 keyof S[K0],\n  K2 extends string \u0026 keyof S[K0][K1],\n  K3 extends string \u0026 keyof S[K0][K1][K2]\n\u003e(path: `${K0}.${K1}.${K2}.${K3}`): (obj: S) =\u003e S[K0][K1][K2][K3];\npath\u003c\n  S,\n  K0 extends keyof S,\n  K1 extends keyof S[K0],\n  K2 extends keyof S[K0][K1],\n  K3 extends keyof S[K0][K1][K2],\n  K4 extends keyof S[K0][K1][K2][K3]\n\u003e(path: [K0, K1, K2, K3, K4]): (obj: S) =\u003e S[K0][K1][K2][K3][K4];\npath\u003c\n  S,\n  K0 extends string \u0026 keyof S,\n  K1 extends string \u0026 keyof S[K0],\n  K2 extends string \u0026 keyof S[K0][K1],\n  K3 extends string \u0026 keyof S[K0][K1][K2],\n  K4 extends string \u0026 keyof S[K0][K1][K2][K3]\n\u003e(path: `${K0}.${K1}.${K2}.${K3}.${K4}`): (obj: S) =\u003e S[K0][K1][K2][K3][K4];\npath\u003c\n  S,\n  K0 extends keyof S,\n  K1 extends keyof S[K0],\n  K2 extends keyof S[K0][K1],\n  K3 extends keyof S[K0][K1][K2],\n  K4 extends keyof S[K0][K1][K2][K3]\n\u003e(path: [K0, K1, K2, K3, K4], obj: S): S[K0][K1][K2][K3][K4];\npath\u003c\n  S,\n  K0 extends keyof S,\n  K1 extends keyof S[K0],\n  K2 extends keyof S[K0][K1],\n  K3 extends keyof S[K0][K1][K2],\n  K4 extends keyof S[K0][K1][K2][K3],\n  K5 extends keyof S[K0][K1][K2][K3][K4]\n\u003e(path: [K0, K1, K2, K3, K4, K5]): (obj: S) =\u003e S[K0][K1][K2][K3][K4][K5];\npath\u003c\n  S,\n  K0 extends string \u0026 keyof S,\n  K1 extends string \u0026 keyof S[K0],\n  K2 extends string \u0026 keyof S[K0][K1],\n  K3 extends string \u0026 keyof S[K0][K1][K2],\n  K4 extends string \u0026 keyof S[K0][K1][K2][K3],\n  K5 extends string \u0026 keyof S[K0][K1][K2][K3][K4]\n\u003e(path: `${K0}.${K1}.${K2}.${K3}.${K4}.${K5}`): (obj: S) =\u003e S[K0][K1][K2][K3][K4][K5];\npath\u003c\n  S,\n  K0 extends keyof S,\n  K1 extends keyof S[K0],\n  K2 extends keyof S[K0][K1],\n  K3 extends keyof S[K0][K1][K2],\n  K4 extends keyof S[K0][K1][K2][K3],\n  K5 extends keyof S[K0][K1][K2][K3][K4]\n\u003e(path: [K0, K1, K2, K3, K4, K5], obj: S): S[K0][K1][K2][K3][K4][K5];\npath\u003c\n  S,\n  K0 extends keyof S,\n  K1 extends keyof S[K0],\n  K2 extends keyof S[K0][K1],\n  K3 extends keyof S[K0][K1][K2],\n  K4 extends keyof S[K0][K1][K2][K3],\n  K5 extends keyof S[K0][K1][K2][K3][K4],\n  K6 extends keyof S[K0][K1][K2][K3][K4][K5]\n\u003e(path: [K0, K1, K2, K3, K4, K5, K6]): (obj: S) =\u003e S[K0][K1][K2][K3][K4][K5][K6];\npath\u003c\n  S,\n  K0 extends string \u0026 keyof S,\n  K1 extends string \u0026 keyof S[K0],\n  K2 extends string \u0026 keyof S[K0][K1],\n  K3 extends string \u0026 keyof S[K0][K1][K2],\n  K4 extends string \u0026 keyof S[K0][K1][K2][K3],\n  K5 extends string \u0026 keyof S[K0][K1][K2][K3][K4],\n  K6 extends string \u0026 keyof S[K0][K1][K2][K3][K4][K5]\n\u003e(path: `${K0}.${K1}.${K2}.${K3}.${K4}.${K5}.${K6}`): (obj: S) =\u003e S[K0][K1][K2][K3][K4][K5][K6];\npath\u003c\n  S,\n  K0 extends keyof S,\n  K1 extends keyof S[K0],\n  K2 extends keyof S[K0][K1],\n  K3 extends keyof S[K0][K1][K2],\n  K4 extends keyof S[K0][K1][K2][K3],\n  K5 extends keyof S[K0][K1][K2][K3][K4],\n  K6 extends keyof S[K0][K1][K2][K3][K4][K5]\n\u003e(path: [K0, K1, K2, K3, K4, K5, K6], obj: S): S[K0][K1][K2][K3][K4][K5][K6];\npath\u003c\n  S,\n  K0 extends keyof S,\n  K1 extends keyof S[K0],\n  K2 extends keyof S[K0][K1],\n  K3 extends keyof S[K0][K1][K2],\n  K4 extends keyof S[K0][K1][K2][K3],\n  K5 extends keyof S[K0][K1][K2][K3][K4],\n  K6 extends keyof S[K0][K1][K2][K3][K4][K5],\n  K7 extends keyof S[K0][K1][K2][K3][K4][K5][K6]\n\u003e(path: [K0, K1, K2, K3, K4, K5, K6, K7]): (obj: S) =\u003e S[K0][K1][K2][K3][K4][K5][K6][K7];\npath\u003c\n  S,\n  K0 extends string \u0026 keyof S,\n  K1 extends string \u0026 keyof S[K0],\n  K2 extends string \u0026 keyof S[K0][K1],\n  K3 extends string \u0026 keyof S[K0][K1][K2],\n  K4 extends string \u0026 keyof S[K0][K1][K2][K3],\n  K5 extends string \u0026 keyof S[K0][K1][K2][K3][K4],\n  K6 extends string \u0026 keyof S[K0][K1][K2][K3][K4][K5],\n  K7 extends string \u0026 keyof S[K0][K1][K2][K3][K4][K5][K6]\n\u003e(path: `${K0}.${K1}.${K2}.${K3}.${K4}.${K5}.${K6}.${K7}`): (obj: S) =\u003e S[K0][K1][K2][K3][K4][K5][K6][K7];\npath\u003c\n  S,\n  K0 extends keyof S,\n  K1 extends keyof S[K0],\n  K2 extends keyof S[K0][K1],\n  K3 extends keyof S[K0][K1][K2],\n  K4 extends keyof S[K0][K1][K2][K3],\n  K5 extends keyof S[K0][K1][K2][K3][K4],\n  K6 extends keyof S[K0][K1][K2][K3][K4][K5],\n  K7 extends keyof S[K0][K1][K2][K3][K4][K5][K6],\n  K8 extends keyof S[K0][K1][K2][K3][K4][K5][K6][K7]\n\u003e(path: [K0, K1, K2, K3, K4, K5, K6, K7, K8]): (obj: S) =\u003e S[K0][K1][K2][K3][K4][K5][K6][K7][K8];\npath\u003c\n  S,\n  K0 extends string \u0026 keyof S,\n  K1 extends string \u0026 keyof S[K0],\n  K2 extends string \u0026 keyof S[K0][K1],\n  K3 extends string \u0026 keyof S[K0][K1][K2],\n  K4 extends string \u0026 keyof S[K0][K1][K2][K3],\n  K5 extends string \u0026 keyof S[K0][K1][K2][K3][K4],\n  K6 extends string \u0026 keyof S[K0][K1][K2][K3][K4][K5],\n  K7 extends string \u0026 keyof S[K0][K1][K2][K3][K4][K5][K6],\n  K8 extends string \u0026 keyof S[K0][K1][K2][K3][K4][K5][K6][K7]\n\u003e(path: `${K0}.${K1}.${K2}.${K3}.${K4}.${K5}.${K6}.${K7}.${K8}`): (obj: S) =\u003e S[K0][K1][K2][K3][K4][K5][K6][K7][K8];\npath\u003cS, K0 extends keyof S\u003e(path: [K0]): (obj: S) =\u003e S[K0];\npath\u003cS, K0 extends keyof S, K1 extends keyof S[K0]\u003e(path: [K0, K1]): (obj: S) =\u003e S[K0][K1];\npath\u003c\n    S,\n    K0 extends keyof S,\n    K1 extends keyof S[K0],\n    K2 extends keyof S[K0][K1]\n\u003e(path: [K0, K1, K2]): (obj: S) =\u003e S[K0][K1][K2];\npath\u003c\n    S,\n    K0 extends keyof S,\n    K1 extends keyof S[K0],\n    K2 extends keyof S[K0][K1],\n    K3 extends keyof S[K0][K1][K2]\n\u003e(path: [K0, K1, K2, K3]): (obj: S) =\u003e S[K0][K1][K2][K3];\npath\u003c\n    S,\n    K0 extends keyof S,\n    K1 extends keyof S[K0],\n    K2 extends keyof S[K0][K1],\n    K3 extends keyof S[K0][K1][K2],\n    K4 extends keyof S[K0][K1][K2][K3]\n\u003e(path: [K0, K1, K2, K3, K4]): (obj: S) =\u003e S[K0][K1][K2][K3][K4];\npath\u003c\n    S,\n    K0 extends keyof S,\n    K1 extends keyof S[K0],\n    K2 extends keyof S[K0][K1],\n    K3 extends keyof S[K0][K1][K2],\n    K4 extends keyof S[K0][K1][K2][K3]\n\u003e(path: [K0, K1, K2, K3, K4], obj: S): S[K0][K1][K2][K3][K4];\npath\u003c\n    S,\n    K0 extends keyof S,\n    K1 extends keyof S[K0],\n    K2 extends keyof S[K0][K1],\n    K3 extends keyof S[K0][K1][K2],\n    K4 extends keyof S[K0][K1][K2][K3],\n    K5 extends keyof S[K0][K1][K2][K3][K4]\n\u003e(path: [K0, K1, K2, K3, K4, K5]): (obj: S) =\u003e S[K0][K1][K2][K3][K4][K5];\npath\u003c\n    S,\n    K0 extends keyof S,\n    K1 extends keyof S[K0],\n    K2 extends keyof S[K0][K1],\n    K3 extends keyof S[K0][K1][K2],\n    K4 extends keyof S[K0][K1][K2][K3],\n    K5 extends keyof S[K0][K1][K2][K3][K4]\n\u003e(path: [K0, K1, K2, K3, K4, K5], obj: S): S[K0][K1][K2][K3][K4][K5];\npath\u003c\n    S,\n    K0 extends keyof S,\n    K1 extends keyof S[K0],\n    K2 extends keyof S[K0][K1],\n    K3 extends keyof S[K0][K1][K2],\n    K4 extends keyof S[K0][K1][K2][K3],\n    K5 extends keyof S[K0][K1][K2][K3][K4],\n    K6 extends keyof S[K0][K1][K2][K3][K4][K5]\n\u003e(path: [K0, K1, K2, K3, K4, K5, K6]): (obj: S) =\u003e S[K0][K1][K2][K3][K4][K5][K6];\npath\u003c\n    S,\n    K0 extends keyof S,\n    K1 extends keyof S[K0],\n    K2 extends keyof S[K0][K1],\n    K3 extends keyof S[K0][K1][K2],\n    K4 extends keyof S[K0][K1][K2][K3],\n    K5 extends keyof S[K0][K1][K2][K3][K4],\n    K6 extends keyof S[K0][K1][K2][K3][K4][K5]\n\u003e(path: [K0, K1, K2, K3, K4, K5, K6], obj: S): S[K0][K1][K2][K3][K4][K5][K6];\npath\u003c\n    S,\n    K0 extends keyof S,\n    K1 extends keyof S[K0],\n    K2 extends keyof S[K0][K1],\n    K3 extends keyof S[K0][K1][K2],\n    K4 extends keyof S[K0][K1][K2][K3],\n    K5 extends keyof S[K0][K1][K2][K3][K4],\n    K6 extends keyof S[K0][K1][K2][K3][K4][K5],\n    K7 extends keyof S[K0][K1][K2][K3][K4][K5][K6]\n\u003e(path: [K0, K1, K2, K3, K4, K5, K6, K7]): (obj: S) =\u003e S[K0][K1][K2][K3][K4][K5][K6][K7];\npath\u003c\n    S,\n    K0 extends keyof S,\n    K1 extends keyof S[K0],\n    K2 extends keyof S[K0][K1],\n    K3 extends keyof S[K0][K1][K2],\n    K4 extends keyof S[K0][K1][K2][K3],\n    K5 extends keyof S[K0][K1][K2][K3][K4],\n    K6 extends keyof S[K0][K1][K2][K3][K4][K5],\n    K7 extends keyof S[K0][K1][K2][K3][K4][K5][K6],\n    K8 extends keyof S[K0][K1][K2][K3][K4][K5][K6][K7]\n\u003e(path: [K0, K1, K2, K3, K4, K5, K6, K7, K8]): (obj: S) =\u003e S[K0][K1][K2][K3][K4][K5][K6][K7][K8];\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.path\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nimport { createPath } from './_internals/createPath.js'\n\nexport function path(pathInput, obj) {\n  if (arguments.length === 1) {\n    return _obj =\u003e path(pathInput, _obj)\n  }\n\n  if (!obj) {\n    return undefined\n  }\n  let willReturn = obj\n  let counter = 0\n\n  const pathArrValue = createPath(pathInput)\n\n  while (counter \u003c pathArrValue.length) {\n    if (willReturn === null || willReturn === undefined) {\n      return undefined\n    }\n    if (willReturn[pathArrValue[counter]] === null) {\n      return undefined\n    }\n\n    willReturn = willReturn[pathArrValue[counter]]\n    counter++\n  }\n\n  return willReturn\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { path } from './path.js'\n\ntest('with array inside object', () =\u003e {\n  const obj = { a: { b: [1, { c: 1 }] } }\n\n  expect(path('a.b.1.c', obj)).toBe(1)\n})\n\ntest('works with undefined', () =\u003e {\n  const obj = { a: { b: { c: 1 } } }\n\n  expect(path('a.b.c.d.f', obj)).toBeUndefined()\n  expect(path('foo.babaz', undefined)).toBeUndefined()\n  expect(path('foo.babaz')(undefined)).toBeUndefined()\n})\n\ntest('works with string instead of array', () =\u003e {\n  expect(path('foo.bar.baz')({ foo: { bar: { baz: 'yes' } } })).toBe('yes')\n})\n\ntest('path', () =\u003e {\n  expect(path(['foo', 'bar', 'baz'])({ foo: { bar: { baz: 'yes' } } })).toBe('yes')\n  expect(path(['foo', 'bar', 'baz'])(null)).toBeUndefined()\n  expect(path(['foo', 'bar', 'baz'])({ foo: { bar: 'baz' } })).toBeUndefined()\n})\n\ntest('with number string in between', () =\u003e {\n  expect(path(['a', '1', 'b'], { a: [{ b: 1 }, { b: 2 }] })).toBe(2)\n})\n\ntest('null is not a valid path', () =\u003e {\n  expect(\n    path('audio_tracks', {\n      a: 1,\n      audio_tracks: null,\n    }),\n  ).toBeUndefined()\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { path, pipe } from 'rambda'\n\nconst input = { a: { b: { c: true } } }\n\ndescribe('R.path with string as path', () =\u003e {\n  it('happy', () =\u003e {\n    const result = pipe(input, path(['a', 'b']))\n    const resultStringInput = pipe(input, path('a.b.c'))\n    result.c // $ExpectType boolean\n    resultStringInput // $ExpectType boolean\n  })\n  it('happy', () =\u003e {\n    const result = pipe([1, 2, 3], path([1]))\n    result // $ExpectType number\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#path)\n\n### permutations\n\n```typescript\n\npermutations\u003cT\u003e(list: T[]): T[][]\n```\n\n```javascript\nconst result = R.permutations(\n\t[1, 2]\n)\n// =\u003e [[1, 2], [2, 1]]\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20result%20%3D%20R.permutations(%0A%09%5B1%2C%202%5D%0A)%0A%2F%2F%20%3D%3E%20%5B%5B1%2C%202%5D%2C%20%5B2%2C%201%5D%5D\"\u003eTry this \u003cstrong\u003eR.permutations\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\npermutations\u003cT\u003e(list: T[]): T[][];\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.permutations\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nimport { cloneList } from './_internals/cloneList.js'\n\n/**\n * Source:\n * https://github.com/denoland/std/blob/main/collections/permutations.ts\n */\nexport function permutations(inputArray) {\n  const result = [];\n  const array = cloneList(inputArray);\n  const k = array.length;\n  if (k === 0) {\n    return result;\n  }\n\n  const c = new Array(k).fill(0);\n\n  result.push([...array]);\n\n  let i = 1;\n\n  while (i \u003c k) {\n    if (c[i] \u003c i) {\n      if (i % 2 === 0) {\n        [array[0], array[i]] = [array[i], array[0]]\n      } else {\n        [array[c[i]], array[i]] = [array[i], array[c[i]]]\n      }\n\n      result.push([...array]);\n\n      c[i] += 1;\n      i = 1;\n    } else {\n      c[i] = 0;\n      i += 1;\n    }\n  }\n\n  return result;\n}\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#permutations)\n\n### pick\n\n```typescript\n\npick\u003cK extends PropertyKey\u003e(propsToPick: K[]): \u003cT\u003e(input: T) =\u003e MergeTypes\u003cPick\u003cT, Exclude\u003ckeyof T, Exclude\u003ckeyof T, K\u003e\u003e\u003e\u003e\n```\n\nIt returns a partial copy of an `input` containing only `propsToPick` properties.\n\n`input` can be either an object or an array.\n\nString annotation of `propsToPick` is one of the differences between `Rambda` and `Ramda`.\n\n\u003e :boom: Typescript Note: Pass explicit type annotation when used with **R.pipe/R.compose** for better type inference\n\n```javascript\nconst obj = {\n  a : 1,\n  b : false,\n  foo: 'cherry'\n}\nconst propsToPick = 'a,foo'\nconst propsToPickList = ['a', 'foo']\n\nconst result = [\n  R.pick(propsToPick)(obj),\n  R.pick(propsToPickList)(obj),\n  R.pick('a,bar')(obj),\n  R.pick('bar')(obj),\n]\n\nconst expected = [\n  {a:1, foo: 'cherry'},\n  {a:1, foo: 'cherry'},\n  {a:1},\n  {},\n]\n// =\u003e `result` is equal to `expected`\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20obj%20%3D%20%7B%0A%20%20a%20%3A%201%2C%0A%20%20b%20%3A%20false%2C%0A%20%20foo%3A%20'cherry'%0A%7D%0Aconst%20propsToPick%20%3D%20'a%2Cfoo'%0Aconst%20propsToPickList%20%3D%20%5B'a'%2C%20'foo'%5D%0A%0Aconst%20result%20%3D%20%5B%0A%20%20R.pick(propsToPick)(obj)%2C%0A%20%20R.pick(propsToPickList)(obj)%2C%0A%20%20R.pick('a%2Cbar')(obj)%2C%0A%20%20R.pick('bar')(obj)%2C%0A%5D%0A%0Aconst%20expected%20%3D%20%5B%0A%20%20%7Ba%3A1%2C%20foo%3A%20'cherry'%7D%2C%0A%20%20%7Ba%3A1%2C%20foo%3A%20'cherry'%7D%2C%0A%20%20%7Ba%3A1%7D%2C%0A%20%20%7B%7D%2C%0A%5D%0A%2F%2F%20%3D%3E%20%60result%60%20is%20equal%20to%20%60expected%60\"\u003eTry this \u003cstrong\u003eR.pick\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\npick\u003cK extends PropertyKey\u003e(propsToPick: K[]): \u003cT\u003e(input: T) =\u003e MergeTypes\u003cPick\u003cT, Exclude\u003ckeyof T, Exclude\u003ckeyof T, K\u003e\u003e\u003e\u003e;\npick\u003c\n\tS extends string,\n\tK extends PickStringToPickPath\u003cK\u003e\n\u003e(propsToPick: S): \u003cT\u003e(input: T) =\u003e MergeTypes\u003cPick\u003cT, Exclude\u003ckeyof T, Exclude\u003ckeyof T, K\u003e\u003e\u003e\u003e;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.pick\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nimport { createPath } from './_internals/createPath.js'\n\nexport function pick(propsToPick) {\n  return input =\u003e {\n    if (!input === null) {\n      return undefined\n    }\n    const keys = createPath(propsToPick, ',')\n    const willReturn = {}\n    let counter = 0\n\n    while (counter \u003c keys.length) {\n      if (keys[counter] in input) {\n        willReturn[keys[counter]] = input[keys[counter]]\n      }\n      counter++\n    }\n\n    return willReturn\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { pick } from './pick.js'\n\nconst obj = {\n  a: 1,\n  b: 2,\n  c: 3,\n}\n\ntest('props to pick is a string', () =\u003e {\n  const result = pick('a,c')(obj)\n  const expectedResult = {\n    a: 1,\n    c: 3,\n  }\n\n  expect(result).toEqual(expectedResult)\n})\n\ntest('when prop is missing', () =\u003e {\n  const result = pick('a,d,f')(obj)\n  expect(result).toEqual({ a: 1 })\n})\n\ntest('props to pick is an array', () =\u003e {\n  expect(\n    pick(['a', 'c'])({\n      a: 'foo',\n      b: 'bar',\n    }),\n  ).toEqual({\n    a: 'foo',\n  })\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { pick, pipe } from 'rambda'\n\nconst input = { a: 'foo', c: 3 }\n\ndescribe('R.pick', () =\u003e {\n  it('with string as input', () =\u003e {\n    const result = pipe(input, pick('a,c,b,o'))\n    result.a // $ExpectType string\n    result.c // $ExpectType number\n  })\n  it('with array as input', () =\u003e {\n    const result = pipe(input, pick(['a', 'c']))\n    result.a // $ExpectType string\n    result.c // $ExpectType number\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#pick)\n\n### pipe\n\nIt performs left-to-right function composition, where first argument is the input for the chain of functions.\n\nThis is huge difference from `Ramda.pipe` where input is passed like `R.pipe(...fns)(input)`.\nHere we have `R.pipe(input, ...fns)`.\n\nIt has much better TypeScript support than `Ramda.pipe` and this is the reason why `Rambda` goes in this direction.\n\n```javascript\nconst result = R.pipe(\n  [1, 2, 3],\n  R.filter(x =\u003e x \u003e 1),\n  R.map(x =\u003e x*10),\n)\n// =\u003e [20, 30]\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20result%20%3D%20R.pipe(%0A%20%20%5B1%2C%202%2C%203%5D%2C%0A%20%20R.filter(x%20%3D%3E%20x%20%3E%201)%2C%0A%20%20R.map(x%20%3D%3E%20x*10)%2C%0A)%0A%2F%2F%20%3D%3E%20%5B20%2C%2030%5D\"\u003eTry this \u003cstrong\u003eR.pipe\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#pipe)\n\n### pipeAsync\n\nIt accepts input as first argument and series of functions as next arguments. It is same as `R.pipe` but with support for asynchronous functions.\n\n```javascript\nconst result = await R.pipeAsync(\n  100,\n  async x =\u003e {\n    await R.delay(100)\n    return x + 2\n  },\n  R.add(2),\n  async x =\u003e {\n    const delayed = await R.delay(100)\n    return delayed + x\n  }\n)\n// `result` resolves to `RAMBDAX_DELAY104`\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20result%20%3D%20await%20R.pipeAsync(%0A%20%20100%2C%0A%20%20async%20x%20%3D%3E%20%7B%0A%20%20%20%20await%20R.delay(100)%0A%20%20%20%20return%20x%20%2B%202%0A%20%20%7D%2C%0A%20%20R.add(2)%2C%0A%20%20async%20x%20%3D%3E%20%7B%0A%20%20%20%20const%20delayed%20%3D%20await%20R.delay(100)%0A%20%20%20%20return%20delayed%20%2B%20x%0A%20%20%7D%0A)%0A%2F%2F%20%60result%60%20resolves%20to%20%60RAMBDAX_DELAY104%60\"\u003eTry this \u003cstrong\u003eR.pipeAsync\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#pipeAsync)\n\n### pluck\n\n```typescript\n\npluck\u003cT, K extends keyof T\u003e(property: K): (list: T[]) =\u003e T[K][]\n```\n\nIt returns list of the values of `property` taken from the all objects inside `list`.\nBasically, this is `R.map(R.prop(property))`.\n\n\u003e :boom: Typescript Note: Pass explicit type annotation when used with **R.pipe/R.compose** for better type inference\n\n```javascript\nconst list = [{a: 1}, {a: 2}, {b: 3}]\nconst property = 'a'\n\nconst result = R.pluck(property)(list) \n// =\u003e [1, 2]\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20list%20%3D%20%5B%7Ba%3A%201%7D%2C%20%7Ba%3A%202%7D%2C%20%7Bb%3A%203%7D%5D%0Aconst%20property%20%3D%20'a'%0A%0Aconst%20result%20%3D%20R.pluck(property)(list)%20%0A%2F%2F%20%3D%3E%20%5B1%2C%202%5D\"\u003eTry this \u003cstrong\u003eR.pluck\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\npluck\u003cT, K extends keyof T\u003e(property: K): (list: T[]) =\u003e T[K][];\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.pluck\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function pluck(property) {\n  return list =\u003e {\n    const willReturn = []\n\n    list.forEach(x =\u003e {\n      if (x[property] !== undefined) {\n        willReturn.push(x[property])\n      }\n    })\n\n    return willReturn\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { pluck } from './pluck.js'\n\ntest('happy', () =\u003e {\n  expect(pluck('a')([{ a: 1 }, { a: 2 }, { b: 1 }])).toEqual([1, 2])\n})\n\ntest('with undefined', () =\u003e {\n  expect(pluck(undefined)([{ a: 1 }, { a: 2 }, { b: 1 }])).toEqual([])\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { pipe, pluck } from 'rambda'\n\nit('R.pluck', () =\u003e {\n  const input = [\n    { a: 1, b: 'foo' },\n    { a: 2, b: 'bar' },\n  ]\n  const result = pipe(input, pluck('b'))\n  result // $ExpectType string[]\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#pluck)\n\n### prepend\n\n```typescript\n\nprepend\u003cT\u003e(xToPrepend: T, iterable: T[]): T[]\n```\n\nIt adds element `x` at the beginning of `list`.\n\n```javascript\nconst result = R.prepend('foo', ['bar', 'baz'])\n// =\u003e ['foo', 'bar', 'baz']\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20result%20%3D%20R.prepend('foo'%2C%20%5B'bar'%2C%20'baz'%5D)%0A%2F%2F%20%3D%3E%20%5B'foo'%2C%20'bar'%2C%20'baz'%5D\"\u003eTry this \u003cstrong\u003eR.prepend\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nprepend\u003cT\u003e(xToPrepend: T, iterable: T[]): T[];\nprepend\u003cT\u003e(xToPrepend: T): (iterable: T[]) =\u003e T[];\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.prepend\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function prepend(x) {\n  return list =\u003e [x].concat(list)\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { prepend } from './prepend.js'\n\ntest('happy', () =\u003e {\n  expect(prepend('yes')(['foo', 'bar', 'baz'])).toEqual(['yes', 'foo', 'bar', 'baz'])\n})\n\ntest('with empty list', () =\u003e {\n  expect(prepend('foo')([])).toEqual(['foo'])\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#prepend)\n\n### prop\n\n```typescript\n\nprop\u003cK extends PropertyKey\u003e(prop: K): \u003cU extends { [P in K]?: unknown }\u003e(obj: U) =\u003e U[K]\n```\n\nIt returns the value of property `propToFind` in `obj`.\n\nIf there is no such property, it returns `undefined`.\n\n```javascript\nconst result = [\n  R.prop('x')({x: 100}), \n  R.prop('x')({a: 1}) \n]\n// =\u003e [100, undefined]\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20result%20%3D%20%5B%0A%20%20R.prop('x')(%7Bx%3A%20100%7D)%2C%20%0A%20%20R.prop('x')(%7Ba%3A%201%7D)%20%0A%5D%0A%2F%2F%20%3D%3E%20%5B100%2C%20undefined%5D\"\u003eTry this \u003cstrong\u003eR.prop\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nprop\u003cK extends PropertyKey\u003e(prop: K): \u003cU extends { [P in K]?: unknown }\u003e(obj: U) =\u003e U[K];\nprop\u003cK extends keyof U, U\u003e(prop: K, obj: U): U[K];\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.prop\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function prop(searchProperty) {\n  return obj =\u003e (obj ? obj[searchProperty] : undefined)\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { map, pipe, prop } from 'rambda'\n\ndescribe('R.prop', () =\u003e {\n  it('happy', () =\u003e {\n    const result = pipe({ a: 1 }, prop('a'))\n\n    result // $ExpectType number\n  })\n  it('alike R.pluck', () =\u003e {\n    const result = pipe([{ a: 1 }, { a: 2 }], map(prop('a')))\n\n    result // $ExpectType number[]\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#prop)\n\n### propEq\n\n```typescript\n\npropEq\u003cT\u003e(val: T): {\n  \u003cK extends PropertyKey\u003e(name: K): (obj: Record\u003cK, T\u003e) =\u003e boolean\n```\n\nIt returns true if `obj` has property `propToFind` and its value is equal to `valueToMatch`.\n\n```javascript\nconst obj = { foo: 'bar' }\nconst secondObj = { foo: 1 }\n\nconst propToFind = 'foo'\nconst valueToMatch = 'bar'\n\nconst result = [\n  R.propEq(propToFind, valueToMatch)(obj),\n  R.propEq(propToFind, valueToMatch)(secondObj)\n]\n// =\u003e [true, false]\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20obj%20%3D%20%7B%20foo%3A%20'bar'%20%7D%0Aconst%20secondObj%20%3D%20%7B%20foo%3A%201%20%7D%0A%0Aconst%20propToFind%20%3D%20'foo'%0Aconst%20valueToMatch%20%3D%20'bar'%0A%0Aconst%20result%20%3D%20%5B%0A%20%20R.propEq(propToFind%2C%20valueToMatch)(obj)%2C%0A%20%20R.propEq(propToFind%2C%20valueToMatch)(secondObj)%0A%5D%0A%2F%2F%20%3D%3E%20%5Btrue%2C%20false%5D\"\u003eTry this \u003cstrong\u003eR.propEq\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\npropEq\u003cT\u003e(val: T): {\n  \u003cK extends PropertyKey\u003e(name: K): (obj: Record\u003cK, T\u003e) =\u003e boolean;\n  \u003cK extends PropertyKey\u003e(name: K, obj: Record\u003cK, T\u003e): boolean;\n};\npropEq\u003cT, K extends PropertyKey\u003e(val: T, name: K): (obj: Record\u003cK, T\u003e) =\u003e boolean;\npropEq\u003cK extends keyof U, U\u003e(val: U[K], name: K, obj: U): boolean;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.propEq\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nimport { equalsFn } from './equals.js'\n\nexport function propEq(valueToMatch, propToFind) {\n  return obj =\u003e {\n    if (!obj) {\n      return false\n    }\n\n    return equalsFn(valueToMatch, obj[propToFind])\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { propEq } from './propEq.js'\n\nconst FOO = 'foo'\nconst BAR = 'bar'\n\ntest('happy', () =\u003e {\n  const obj = { [FOO]: BAR }\n  expect(propEq(BAR, FOO)(obj)).toBeTruthy()\n  expect(propEq(1, FOO)(obj)).toBeFalsy()\n  expect(propEq(1, 1)(null)).toBeFalsy()\n})\n\ntest('returns false if called with a null or undefined object', () =\u003e {\n  expect(propEq('name', 'Abby')(null)).toBeFalsy()\n  expect(propEq('name', 'Abby')(undefined)).toBeFalsy()\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#propEq)\n\n### propOr\n\n```typescript\n\npropOr\u003cT, P extends string\u003e(defaultValue: T, property: P): (obj: Partial\u003cRecord\u003cP, T\u003e\u003e) =\u003e T\n```\n\nIt returns either `defaultValue` or the value of `property` in `obj`.\n\n```javascript\nconst obj = {a: 1}\nconst defaultValue = 'DEFAULT_VALUE'\nconst property = 'a'\n\nconst result = [\n  R.propOr(defaultValue, property)(obj),\n  R.propOr(defaultValue, 'foo')(obj)\n]\n// =\u003e [1, 'DEFAULT_VALUE']\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20obj%20%3D%20%7Ba%3A%201%7D%0Aconst%20defaultValue%20%3D%20'DEFAULT_VALUE'%0Aconst%20property%20%3D%20'a'%0A%0Aconst%20result%20%3D%20%5B%0A%20%20R.propOr(defaultValue%2C%20property)(obj)%2C%0A%20%20R.propOr(defaultValue%2C%20'foo')(obj)%0A%5D%0A%2F%2F%20%3D%3E%20%5B1%2C%20'DEFAULT_VALUE'%5D\"\u003eTry this \u003cstrong\u003eR.propOr\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\npropOr\u003cT, P extends string\u003e(defaultValue: T, property: P): (obj: Partial\u003cRecord\u003cP, T\u003e\u003e) =\u003e T;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.propOr\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nimport { defaultTo } from './defaultTo.js'\n\nexport function propOr(defaultValue, property) {\n  return obj =\u003e {\n    if (!obj) {\n      return defaultValue\n    }\n\n    return defaultTo(defaultValue, obj[property])\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { propOr } from './propOr.js'\n\ntest('propOr', () =\u003e {\n  const obj = { a: 1 }\n  expect(propOr('default', 'a')(obj)).toBe(1)\n  expect(propOr('default', 'notExist')(obj)).toBe('default')\n  expect(propOr('default', 'notExist')(null)).toBe('default')\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { propOr } from 'rambda'\n\nconst obj = { foo: 'bar' }\nconst property = 'foo'\nconst fallback = 'fallback'\n\ndescribe('R.propOr', () =\u003e {\n  it('happy', () =\u003e {\n    const result = propOr(fallback, property)(obj)\n    result // $ExpectType string\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#propOr)\n\n### propSatisfies\n\n```typescript\n\npropSatisfies\u003cT\u003e(predicate: (x: T) =\u003e boolean, property: string): (obj: Record\u003cPropertyKey, T\u003e) =\u003e boolean\n```\n\nIt returns `true` if the object property satisfies a given predicate.\n\n```javascript\nconst obj = {a: {b:1}}\nconst property = 'a'\nconst predicate = x =\u003e x?.b === 1\n\nconst result = R.propSatisfies(predicate, property, obj)\n// =\u003e true\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20obj%20%3D%20%7Ba%3A%20%7Bb%3A1%7D%7D%0Aconst%20property%20%3D%20'a'%0Aconst%20predicate%20%3D%20x%20%3D%3E%20x%3F.b%20%3D%3D%3D%201%0A%0Aconst%20result%20%3D%20R.propSatisfies(predicate%2C%20property%2C%20obj)%0A%2F%2F%20%3D%3E%20true\"\u003eTry this \u003cstrong\u003eR.propSatisfies\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\npropSatisfies\u003cT\u003e(predicate: (x: T) =\u003e boolean, property: string): (obj: Record\u003cPropertyKey, T\u003e) =\u003e boolean;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.propSatisfies\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function propSatisfies(predicate, property) {\n  return obj =\u003e predicate(obj[property])\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { propSatisfies } from './propSatisfies.js'\n\nconst obj = { a: 1 }\n\ntest('when true', () =\u003e {\n  expect(propSatisfies(x =\u003e x \u003e 0, 'a')(obj)).toBeTruthy()\n})\n\ntest('when false', () =\u003e {\n  expect(propSatisfies(x =\u003e x \u003c 0, 'a')(obj)).toBeFalsy()\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { pipe, propSatisfies } from 'rambda'\n\nconst obj = { a: 1 }\n\ndescribe('R.propSatisfies', () =\u003e {\n  it('happy', () =\u003e {\n    const result = pipe(\n      obj,\n      propSatisfies(x =\u003e {\n        x // $ExpectType number\n        return x \u003e 0\n      }, 'a'),\n    )\n\n    result // $ExpectType boolean\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#propSatisfies)\n\n### range\n\n```typescript\n\nrange(startInclusive: number): (endExclusive: number) =\u003e number[]\n```\n\nIt returns list of numbers between `startInclusive` to `endInclusive` markers.\n\n```javascript\nR.range(0)(5)\n// =\u003e [0, 1, 2, 3, 4, 5]\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20result%20%3D%20R.range(0)(5)%0A%2F%2F%20%3D%3E%20%5B0%2C%201%2C%202%2C%203%2C%204%2C%205%5D\"\u003eTry this \u003cstrong\u003eR.range\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nrange(startInclusive: number): (endExclusive: number) =\u003e number[];\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.range\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function range(start) {\n  return end =\u003e {\n    if (Number.isNaN(Number(start)) || Number.isNaN(Number(end))) {\n      throw new TypeError('Both arguments to range must be numbers')\n    }\n\n    if (end \u003c= start) {\n      return []\n    }\n\n    const len = end - start\n    const willReturn = Array(len)\n\n    for (let i = 0; i \u003c len + 1; i++) {\n      willReturn[i] = start + i\n    }\n\n    return willReturn\n  }\n}\n\nexport function rangeDescending(start) {\n  return end =\u003e {\n    if (Number.isNaN(Number(start)) || Number.isNaN(Number(end))) {\n      throw new TypeError('Both arguments to range must be numbers')\n    }\n\n    if (end \u003e= start) {\n      return []\n    }\n\n    const len = start - end\n    const willReturn = Array(len)\n\n    for (let i = 0; i \u003c len + 1; i++) {\n      willReturn[i] = start - i\n    }\n\n    return willReturn\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { range, rangeDescending } from './range.js'\n\ntest('happy', () =\u003e {\n  expect(range(0)(10)).toEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])\n})\n\ntest('end range is bigger than start range', () =\u003e {\n  expect(range(7)(3)).toEqual([])\n  expect(range(5)(5)).toEqual([])\n})\n\ntest('descending', () =\u003e {\n\texpect(rangeDescending(5)(0)).toEqual([5, 4, 3, 2, 1, 0])\n})\n\ntest('descending end range is bigger than start range', () =\u003e {\n\texpect(rangeDescending(3)(7)).toEqual([])\n\texpect(rangeDescending(5)(5)).toEqual([])\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { range } from 'rambda'\n\ndescribe('R.range', () =\u003e {\n  it('curried', () =\u003e {\n    const result = range(1)(4)\n\n    result // $ExpectType number[]\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#range)\n\n### rangeDescending\n\n```typescript\n\nrangeDescending(startInclusive: number): (endExclusive: number) =\u003e number[]\n```\n\nSame as `R.range` but in descending order.\n\n```javascript\nR.rangeDescending(5, 0)\n// =\u003e [5, 4, 3, 2, 1, 0]\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20result%20%3D%20R.rangeDescending(5%2C%200)%0A%2F%2F%20%3D%3E%20%5B5%2C%204%2C%203%2C%202%2C%201%2C%200%5D\"\u003eTry this \u003cstrong\u003eR.rangeDescending\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nrangeDescending(startInclusive: number): (endExclusive: number) =\u003e number[];\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#rangeDescending)\n\n### reduce\n\n\u003e :boom: It passes index of the list as third argument to `reducer` function.\n\n```javascript\nconst list = [1, 2, 3]\nconst initialValue = 10\nconst reducer = (prev, current) =\u003e prev * current\n\nconst result = R.reduce(reducer, initialValue, list)\n// =\u003e 60\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20list%20%3D%20%5B1%2C%202%2C%203%5D%0Aconst%20initialValue%20%3D%2010%0Aconst%20reducer%20%3D%20(prev%2C%20current)%20%3D%3E%20prev%20*%20current%0A%0Aconst%20result%20%3D%20R.reduce(reducer%2C%20initialValue%2C%20list)%0A%2F%2F%20%3D%3E%2060\"\u003eTry this \u003cstrong\u003eR.reduce\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#reduce)\n\n### reject\n\n```typescript\n\nreject\u003cT\u003e(\n\tpredicate: (value: T) =\u003e boolean,\n  list: T[],\n): T[]\n```\n\nIt has the opposite effect of `R.filter`.\n\n```javascript\nconst list = [1, 2, 3, 4]\nconst obj = {a: 1, b: 2}\nconst predicate = x =\u003e x \u003e 1\n\nconst result = [\n  R.reject(predicate)(list),\n  R.reject(predicate)(obj)\n]\n// =\u003e [[1], {a: 1}]\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20list%20%3D%20%5B1%2C%202%2C%203%2C%204%5D%0Aconst%20obj%20%3D%20%7Ba%3A%201%2C%20b%3A%202%7D%0Aconst%20predicate%20%3D%20x%20%3D%3E%20x%20%3E%201%0A%0Aconst%20result%20%3D%20%5B%0A%20%20R.reject(predicate)(list)%2C%0A%20%20R.reject(predicate)(obj)%0A%5D%0A%2F%2F%20%3D%3E%20%5B%5B1%5D%2C%20%7Ba%3A%201%7D%5D\"\u003eTry this \u003cstrong\u003eR.reject\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nreject\u003cT\u003e(\n\tpredicate: (value: T) =\u003e boolean,\n  list: T[],\n): T[];\nreject\u003cT\u003e(\n\tpredicate: BooleanConstructor,\n): (list: readonly T[]) =\u003e (\"\" | null | undefined | false | 0)[];\nreject\u003cT\u003e(\n\tpredicate: BooleanConstructor,\n): (list: T[]) =\u003e (\"\" | null | undefined | false | 0)[];\nreject\u003cT\u003e(\n\tpredicate: (value: T) =\u003e boolean,\n): (list: T[]) =\u003e T[];\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.reject\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nimport { filter } from './filter.js'\n\nexport function reject(predicate) {\n  return list =\u003e filter(x =\u003e !predicate(x))(list)\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { reject } from './reject.js'\n\ntest('happy', () =\u003e {\n  const isEven = n =\u003e n % 2 === 0\n\n  expect(reject(isEven)([1, 2, 3, 4])).toEqual([1, 3])\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { reject, pipe } from 'rambda'\n\nconst list = [1, 2, 3]\n\ndescribe('R.reject with array', () =\u003e {\n  it('within pipe', () =\u003e {\n    const result = pipe(\n      list,\n      reject(x =\u003e {\n        x // $ExpectType number\n        return x \u003e 1\n      }),\n    )\n    result // $ExpectType number[]\n  })\n  it('narrowing type', () =\u003e {\n    interface Foo {\n      a: number\n    }\n    interface Bar extends Foo {\n      b: string\n    }\n    interface Baz extends Foo {\n      c: string\n    }\n\n    const testList: (Foo | Bar | Baz)[] = [{ a: 1 }, { a: 2 }, { a: 3 }]\n    const rejectBar = (x: Foo | Bar | Baz): x is Bar =\u003e {\n      return typeof (x as Bar).b === 'string'\n    }\n    const result = pipe(\n      testList,\n      reject(rejectBar),\n    )\n    result // $ExpectType (Foo | Baz)[]\n  })\n  it('narrowing type - readonly', () =\u003e {\n\t\tinterface Foo {\n      a: number\n    }\n    interface Bar extends Foo {\n      b: string\n    }\n    interface Baz extends Foo {\n      c: string\n    }\n\n    const testList: (Foo | Bar | Baz)[] = [{ a: 1 }, { a: 2 }, { a: 3 }] as const\n    const rejectBar = (x: Foo | Bar | Baz): x is Bar =\u003e {\n      return typeof (x as Bar).b === 'string'\n    }\n    const result = pipe(\n      testList,\n      reject(rejectBar),\n    )\n    result // $ExpectType (Foo | Baz)[]\n  })\n  it('rejecting NonNullable', () =\u003e {\n    const testList = [1, 2, null, undefined, 3]\n    const result = pipe(testList, reject(Boolean))\n    result // $ExpectType (null | undefined)[]\n  })\n  it('rejecting NonNullable - readonly', () =\u003e {\n    const testList = [1, 2, null, undefined, 3] as const\n    const result = pipe(testList, reject(Boolean))\n    result // $ExpectType (null | undefined)[]\n    // @ts-expect-error\n    result.includes(1)\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#reject)\n\n### rejectObject\n\n```typescript\n\nrejectObject\u003cT extends object\u003e(\n  valueMapper: (\n    value: EnumerableStringKeyedValueOf\u003cT\u003e,\n    key: EnumerableStringKeyOf\u003cT\u003e,\n    data: T,\n  ) =\u003e boolean,\n): \u003cU extends T\u003e(data: T) =\u003e U\n```\n\nSame as `R.filterObject` but it returns the object with properties that do not satisfy the predicate function.\n\n```javascript\nconst result = R.rejectObject(\n\t(val, prop) =\u003e prop === 'a' || val \u003e 1\n)({a: 1, b: 2, c:3})\n// =\u003e {b: 2}\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20result%20%3D%20R.rejectObject(%0A%09(val%2C%20prop)%20%3D%3E%20prop%20%3D%3D%3D%20'a'%20%7C%7C%20val%20%3E%201%0A)(%7Ba%3A%201%2C%20b%3A%202%2C%20c%3A3%7D)%0A%2F%2F%20%3D%3E%20%7Bb%3A%202%7D\"\u003eTry this \u003cstrong\u003eR.rejectObject\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nrejectObject\u003cT extends object\u003e(\n  valueMapper: (\n    value: EnumerableStringKeyedValueOf\u003cT\u003e,\n    key: EnumerableStringKeyOf\u003cT\u003e,\n    data: T,\n  ) =\u003e boolean,\n): \u003cU extends T\u003e(data: T) =\u003e U;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.rejectObject\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function rejectObject(predicate) {\n  return obj =\u003e {\n    const willReturn = {}\n\n    for (const prop in obj) {\n      if (!predicate(obj[prop], prop, obj)) {\n        willReturn[prop] = obj[prop]\n      }\n    }\n\n    return willReturn\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { pipe } from './pipe.js'\nimport { rejectObject } from './rejectObject.js'\n\ntest('happy', () =\u003e {\n\tlet testInput = { a: 1, b: 2, c: 3 }\n  const result = pipe(\n\t\ttestInput,\n\t\trejectObject((x, prop, obj) =\u003e {\n\t\t\texpect(prop).toBeOneOf(['a', 'b', 'c'])\n\t\t\texpect(obj).toBe(testInput)\n\t\t\treturn x \u003e 1\n\t\t})\n\t)\n\texpect(result).toEqual({ a:1 })\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { filterObject, pipe } from 'rambda'\n\ndescribe('R.filterObject', () =\u003e {\n  it('require explicit type', () =\u003e {\n    const result = pipe(\n      { a: 1, b: 2 },\n      filterObject\u003c{ b: number }\u003e(a =\u003e {\n        a // $ExpectType number\n        return a \u003e 1\n      }),\n    )\n    result.b // $ExpectType number\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#rejectObject)\n\n### replace\n\n```typescript\n\nreplace(strOrRegex: RegExp | string, replacer: RegExp | string): (str: string) =\u003e string\n```\n\nIt replaces `strOrRegex` found in `str` with `replacer`.\n\n```javascript\nconst result = [\n\tR.replace('o', '|1|')('foo'),\n\tR.replace(/o/g, '|1|')('foo'),\n]\n// =\u003e ['f|1|o', 'f|1||1|']\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20result%20%3D%20%5B%0A%09R.replace('o'%2C%20'%7C1%7C')('foo')%2C%0A%09R.replace(%2Fo%2Fg%2C%20'%7C1%7C')('foo')%2C%0A%5D%0A%2F%2F%20%3D%3E%20%5B'f%7C1%7Co'%2C%20'f%7C1%7C%7C1%7C'%5D\"\u003eTry this \u003cstrong\u003eR.replace\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nreplace(strOrRegex: RegExp | string, replacer: RegExp | string): (str: string) =\u003e string;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.replace\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function replace(pattern, replacer) {\n  return str =\u003e str.replace(pattern, replacer)\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { replace } from './replace.js'\n\ntest('happy', () =\u003e {\n  expect(replace(/\\s/g, '|')('foo bar baz')).toBe('foo|bar|baz')\n  expect(replace('a', '|')('foo bar baz')).toBe('foo b|r baz')\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { replace } from 'rambda'\n\nconst str = 'foo bar foo'\nconst replacer = 'bar'\n\ndescribe('R.replace', () =\u003e {\n  it('happy', () =\u003e {\n    const result = replace(/foo/g, replacer)(str)\n\n    result // $ExpectType string\n  })\n  it('with string as search pattern', () =\u003e {\n    const result = replace('foo', replacer)(str)\n\n    result // $ExpectType string\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#replace)\n\n### replaceItemAtIndex\n\n```typescript\n\nreplaceItemAtIndex\u003cT\u003e(index: number, replaceFn: (x: T) =\u003e T): (list: T[]) =\u003e T[]\n```\n\nIt replaces `index` in array `list` with the result of `replaceFn(list[i])`.\n\n```javascript\nconst result = R.pipe(\n\t[1, 2, 3],\n\tR.replaceItemAtIndex(1, R.add(1))\n) // =\u003e [1, 3, 3]\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20result%20%3D%20R.pipe(%0A%09%5B1%2C%202%2C%203%5D%2C%0A%09R.replaceItemAtIndex(1%2C%20R.add(1))%0A)%20%2F%2F%20%3D%3E%20%5B1%2C%203%2C%203%5D\"\u003eTry this \u003cstrong\u003eR.replaceItemAtIndex\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nreplaceItemAtIndex\u003cT\u003e(index: number, replaceFn: (x: T) =\u003e T): (list: T[]) =\u003e T[];\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.replaceItemAtIndex\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nimport { cloneList } from './_internals/cloneList.js'\n\nexport function replaceItemAtIndex(index, replaceFn) {\n  return list =\u003e {\n    const actualIndex = index \u003c 0 ? list.length + index : index\n    if (index \u003e= list.length || actualIndex \u003c 0) {\n      return list\n    }\n\n    const clone = cloneList(list)\n    clone[actualIndex] = replaceFn(clone[actualIndex])\n\n    return clone\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { replaceItemAtIndex } from './replaceItemAtIndex.js'\n\nconst add10 = x =\u003e x + 10\n\nconst list = [0, 1, 2]\nconst expected = [0, 11, 2]\n\ntest('happy', () =\u003e {\n  expect(replaceItemAtIndex(1, add10)(list)).toEqual(expected)\n})\n\ntest('with negative index', () =\u003e {\n  expect(replaceItemAtIndex(-2, add10)(list)).toEqual(expected)\n})\n\ntest('when index is out of bounds', () =\u003e {\n  const list = [0, 1, 2, 3]\n  expect(replaceItemAtIndex(4, add10)(list)).toEqual(list)\n  expect(replaceItemAtIndex(-5, add10)(list)).toEqual(list)\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#replaceItemAtIndex)\n\n### shuffle\n\n```typescript\n\nshuffle\u003cT\u003e(list: T[]): T[]\n```\n\nIt returns a randomized copy of array.\n\n```javascript\nconst result = R.shuffle(\n\t[1, 2, 3]\n)\n// =\u003e [3, 1, 2] or [2, 3, 1] or ...\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20result%20%3D%20R.shuffle(%0A%09%5B1%2C%202%2C%203%5D%0A)%0A%2F%2F%20%3D%3E%20%5B3%2C%201%2C%202%5D%20or%20%5B2%2C%203%2C%201%5D%20or%20...\"\u003eTry this \u003cstrong\u003eR.shuffle\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nshuffle\u003cT\u003e(list: T[]): T[];\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.shuffle\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function shuffle(listInput) {\n  const list = cloneList(listInput)\n  let counter = list.length\n  while (counter \u003e 0) {\n    const index = Math.floor(Math.random() * counter)\n    counter--\n    const temp = list[counter]\n    list[counter] = list[index]\n    list[index] = temp\n  }\n\n  return list\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { shuffle } from 'rambdax'\n\nconst list = [1, 2, 3, 4, 5]\n\ndescribe('R.shuffle', () =\u003e {\n  it('happy', () =\u003e {\n    const result = shuffle(list)\n    result // $ExpectType number[]\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#shuffle)\n\n### sort\n\n```typescript\n\nsort\u003cT\u003e(sortFn: (a: T, b: T) =\u003e number): (list: T[]) =\u003e T[]\n```\n\nIt returns copy of `list` sorted by `sortFn` function, where `sortFn` needs to return only `-1`, `0` or `1`.\n\n```javascript\nconst list = [\n  {a: 2},\n  {a: 3},\n  {a: 1}\n]\nconst sortFn = (x, y) =\u003e {\n  return x.a \u003e y.a ? 1 : -1\n}\n\nconst result = R.sort(sortFn, list)\nconst expected = [\n  {a: 1},\n  {a: 2},\n  {a: 3}\n]\n// =\u003e `result` is equal to `expected`\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20list%20%3D%20%5B%0A%20%20%7Ba%3A%202%7D%2C%0A%20%20%7Ba%3A%203%7D%2C%0A%20%20%7Ba%3A%201%7D%0A%5D%0Aconst%20sortFn%20%3D%20(x%2C%20y)%20%3D%3E%20%7B%0A%20%20return%20x.a%20%3E%20y.a%20%3F%201%20%3A%20-1%0A%7D%0A%0Aconst%20result%20%3D%20R.sort(sortFn%2C%20list)%0Aconst%20expected%20%3D%20%5B%0A%20%20%7Ba%3A%201%7D%2C%0A%20%20%7Ba%3A%202%7D%2C%0A%20%20%7Ba%3A%203%7D%0A%5D%0A%2F%2F%20%3D%3E%20%60result%60%20is%20equal%20to%20%60expected%60\"\u003eTry this \u003cstrong\u003eR.sort\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nsort\u003cT\u003e(sortFn: (a: T, b: T) =\u003e number): (list: T[]) =\u003e T[];\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.sort\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nimport { cloneList } from './_internals/cloneList.js'\n\nexport function sort(sortFn) {\n  return list =\u003e cloneList(list).sort(sortFn)\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { sort } from './sort.js'\n\nconst fn = (a, b) =\u003e (a \u003e b ? 1 : -1)\n\ntest('sort', () =\u003e {\n  expect(sort((a, b) =\u003e a - b)([2, 3, 1])).toEqual([1, 2, 3])\n})\n\ntest(\"it doesn't mutate\", () =\u003e {\n  const list = ['foo', 'bar', 'baz']\n\n  expect(sort(fn)(list)).toEqual(['bar', 'baz', 'foo'])\n  expect(list).toEqual(['foo', 'bar', 'baz'])\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { pipe, sort } from 'rambda'\n\nconst list = [3, 0, 5, 2, 1]\n\ndescribe('R.sort', () =\u003e {\n  it('happy', () =\u003e {\n    const result = sort\u003cnumber\u003e((a, b) =\u003e {\n      return a \u003e b ? 1 : -1\n    })(list)\n    result // $ExpectType number[]\n  })\n  it('within pipe', () =\u003e {\n    const result = pipe(\n      list,\n      sort((a, b) =\u003e {\n        return a \u003e b ? 1 : -1\n      }),\n    )\n    result // $ExpectType number[]\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#sort)\n\n### sortBy\n\n```typescript\n\nsortBy\u003cT\u003e(sortFn: (x: T) =\u003e Ord): (list: T[]) =\u003e T[]\n```\n\nIt returns copy of `list` sorted by `sortFn` function, where `sortFn` function returns a value to compare, i.e. it doesn't need to return only `-1`, `0` or `1`.\n\n```javascript\nconst list = [\n  {a: 2},\n  {a: 3},\n  {a: 1}\n]\nconst sortFn = x =\u003e x.a\n\nconst result = R.sortBy(sortFn, list)\nconst expected = [\n  {a: 1},\n  {a: 2},\n  {a: 3}\n]\n// =\u003e `result` is equal to `expected`\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20list%20%3D%20%5B%0A%20%20%7Ba%3A%202%7D%2C%0A%20%20%7Ba%3A%203%7D%2C%0A%20%20%7Ba%3A%201%7D%0A%5D%0Aconst%20sortFn%20%3D%20x%20%3D%3E%20x.a%0A%0Aconst%20result%20%3D%20R.sortBy(sortFn%2C%20list)%0Aconst%20expected%20%3D%20%5B%0A%20%20%7Ba%3A%201%7D%2C%0A%20%20%7Ba%3A%202%7D%2C%0A%20%20%7Ba%3A%203%7D%0A%5D%0A%2F%2F%20%3D%3E%20%60result%60%20is%20equal%20to%20%60expected%60\"\u003eTry this \u003cstrong\u003eR.sortBy\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nsortBy\u003cT\u003e(sortFn: (x: T) =\u003e Ord): (list: T[]) =\u003e T[];\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.sortBy\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nimport { cloneList } from './_internals/cloneList.js'\n\nexport function sortBy(sortFn) {\n  return list =\u003e {\n    const clone = cloneList(list)\n\n    return clone.sort((a, b) =\u003e {\n      const aSortResult = sortFn(a)\n      const bSortResult = sortFn(b)\n\n      if (aSortResult === bSortResult) {\n        return 0\n      }\n\n      return aSortResult \u003c bSortResult ? -1 : 1\n    })\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { sortBy } from './sortBy.js'\n\ntest('happy', () =\u003e {\n  const input = [{ a: 2 }, { a: 1 }, { a: 1 }, { a: 3 }]\n  const expected = [{ a: 1 }, { a: 1 }, { a: 2 }, { a: 3 }]\n\n  const result = sortBy(x =\u003e x.a)(input)\n  expect(result).toEqual(expected)\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { pipe, sortBy } from 'rambda'\n\ndescribe('R.sortBy', () =\u003e {\n  it('passing type to sort function and list', () =\u003e {\n    const result = pipe(\n      [{ a: 2 }, { a: 1 }, { a: 0 }],\n      sortBy(x =\u003e {\n        return x.a\n      }),\n    )\n\n    result[0].a // $ExpectType number\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#sortBy)\n\n### sortObject\n\n```typescript\n\nsortObject\u003cT, K extends string \u0026 keyof T\u003e(predicate: (aProp: string, bProp: string, aValue: T[K], bValue: T[K]) =\u003e number): (obj: T) =\u003e T\n```\n\nIt returns a sorted version of `input` object.\n\n```javascript\nconst predicate = (propA, propB, valueA, valueB) =\u003e valueA \u003e valueB ? -1 : 1\n\nconst result = R.sortObject(predicate, {a:1, b: 4, c: 2})\n// =\u003e {b: 4, c: 2, a: 1}\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20predicate%20%3D%20(propA%2C%20propB%2C%20valueA%2C%20valueB)%20%3D%3E%20valueA%20%3E%20valueB%20%3F%20-1%20%3A%201%0A%0Aconst%20result%20%3D%20R.sortObject(predicate%2C%20%7Ba%3A1%2C%20b%3A%204%2C%20c%3A%202%7D)%0A%2F%2F%20%3D%3E%20%7Bb%3A%204%2C%20c%3A%202%2C%20a%3A%201%7D\"\u003eTry this \u003cstrong\u003eR.sortObject\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nsortObject\u003cT, K extends string \u0026 keyof T\u003e(predicate: (aProp: string, bProp: string, aValue: T[K], bValue: T[K]) =\u003e number): (obj: T) =\u003e T;\nsortObject\u003cT\u003e(predicate: (aProp: string, bProp: string) =\u003e number): (obj: T) =\u003e T;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.sortObject\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nimport { sort } from './sort.js'\n\nexport function sortObject(predicate) {\n  return obj =\u003e {\n    const keys = Object.keys(obj)\n    const sortedKeys = sort((a, b) =\u003e predicate(a, b, obj[a], obj[b]))(keys)\n\n    const toReturn = {}\n    sortedKeys.forEach(singleKey =\u003e {\n      toReturn[singleKey] = obj[singleKey]\n    })\n\n    return toReturn\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { sortObject } from './sortObject.js'\n\nconst obj = {\n  c: 7,\n  a: 100,\n  b: 1,\n  d: 4,\n}\n\ntest('happy', () =\u003e {\n  const predicate = (a, b, aValue, bValue) =\u003e {\n    if (a === 'a') {\n      return -1\n    }\n    if (b === 'a') {\n      return 1\n    }\n    return aValue \u003e bValue ? -1 : 1\n  }\n  const result = sortObject(predicate)(obj)\n  const expected = {\n    a: 100,\n    c: 7,\n    d: 4,\n    b: 1,\n  }\n  expect(result).toEqual(expected)\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { sortObject, pipe } from 'rambda'\n\nconst obj = {\n  c: 1,\n  a: 2,\n  b: 3,\n}\n\ndescribe('R.sortObject', () =\u003e {\n  it('predicate with all arguments', () =\u003e {\n    const result = pipe(\n      obj,\n      sortObject((propA, propB, valueA, valueB) =\u003e {\n        propA // $ExpectType string\n        propB // $ExpectType string\n        valueA // $ExpectType number\n        valueB // $ExpectType number\n        return propA \u003e propB ? -1 : 1\n      }),\n    )\n\n    result // $ExpectType { c: number; a: number; b: number; }\n  })\n\n  it('predicate with only property arguments', () =\u003e {\n    const result = pipe(\n      obj,\n      sortObject((propA, propB) =\u003e {\n        propA // $ExpectType string\n        propB // $ExpectType string\n        return propA \u003e propB ? -1 : 1\n      }),\n    )\n    result // $ExpectType { c: number; a: number; b: number; }\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#sortObject)\n\n### sortWith\n\n```javascript\nconst result = R.sortWith([\n    (a, b) =\u003e a.a === b.a ? 0 : a.a \u003e b.a ? 1 : -1,\n    (a, b) =\u003e a.b === b.b ? 0 : a.b \u003e b.b ? 1 : -1,\n])([\n  {a: 1, b: 2},\n  {a: 2, b: 1},\n  {a: 2, b: 2},\n  {a: 1, b: 1},\n])\nconst expected = [\n  {a: 1, b: 1},\n  {a: 1, b: 2},\n  {a: 2, b: 1},\n  {a: 2, b: 2},\n]\n// =\u003e `result` is equal to `expected`\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20result%20%3D%20R.sortWith(%5B%0A%20%20%20%20(a%2C%20b)%20%3D%3E%20a.a%20%3D%3D%3D%20b.a%20%3F%200%20%3A%20a.a%20%3E%20b.a%20%3F%201%20%3A%20-1%2C%0A%20%20%20%20(a%2C%20b)%20%3D%3E%20a.b%20%3D%3D%3D%20b.b%20%3F%200%20%3A%20a.b%20%3E%20b.b%20%3F%201%20%3A%20-1%2C%0A%5D)(%5B%0A%20%20%7Ba%3A%201%2C%20b%3A%202%7D%2C%0A%20%20%7Ba%3A%202%2C%20b%3A%201%7D%2C%0A%20%20%7Ba%3A%202%2C%20b%3A%202%7D%2C%0A%20%20%7Ba%3A%201%2C%20b%3A%201%7D%2C%0A%5D)%0Aconst%20expected%20%3D%20%5B%0A%20%20%7Ba%3A%201%2C%20b%3A%201%7D%2C%0A%20%20%7Ba%3A%201%2C%20b%3A%202%7D%2C%0A%20%20%7Ba%3A%202%2C%20b%3A%201%7D%2C%0A%20%20%7Ba%3A%202%2C%20b%3A%202%7D%2C%0A%5D%0A%2F%2F%20%3D%3E%20%60result%60%20is%20equal%20to%20%60expected%60\"\u003eTry this \u003cstrong\u003eR.sortWith\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#sortWith)\n\n### split\n\n```typescript\n\nsplit(separator: string | RegExp): (str: string) =\u003e string[]\n```\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nsplit(separator: string | RegExp): (str: string) =\u003e string[];\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.split\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function split(separator) {\n  return str =\u003e str.split(separator)\n}\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#split)\n\n### splitEvery\n\n```typescript\n\nsplitEvery\u003cT\u003e(sliceLength: number): (input: T[]) =\u003e (T[])[]\n```\n\nIt splits `input` into slices of `sliceLength`.\n\n```javascript\nconst result = [\n  R.splitEvery(2, [1, 2, 3]), \n  R.splitEvery(3, 'foobar') \n]\n\nconst expected = [\n  [[1, 2], [3]],\n  ['foo', 'bar']\n]\n// =\u003e `result` is equal to `expected`\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20result%20%3D%20%5B%0A%20%20R.splitEvery(2%2C%20%5B1%2C%202%2C%203%5D)%2C%20%0A%20%20R.splitEvery(3%2C%20'foobar')%20%0A%5D%0A%0Aconst%20expected%20%3D%20%5B%0A%20%20%5B%5B1%2C%202%5D%2C%20%5B3%5D%5D%2C%0A%20%20%5B'foo'%2C%20'bar'%5D%0A%5D%0A%2F%2F%20%3D%3E%20%60result%60%20is%20equal%20to%20%60expected%60\"\u003eTry this \u003cstrong\u003eR.splitEvery\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nsplitEvery\u003cT\u003e(sliceLength: number): (input: T[]) =\u003e (T[])[];\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.splitEvery\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function splitEvery(sliceLength) {\n  return list =\u003e {\n    if (sliceLength \u003c 1) {\n      throw new Error('First argument to splitEvery must be a positive integer')\n    }\n\n    const willReturn = []\n    let counter = 0\n\n    while (counter \u003c list.length) {\n      willReturn.push(list.slice(counter, (counter += sliceLength)))\n    }\n\n    return willReturn\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { splitEvery } from './splitEvery.js'\n\ntest('happy', () =\u003e {\n  expect(splitEvery(3)([1, 2, 3, 4, 5, 6, 7])).toEqual([[1, 2, 3], [4, 5, 6], [7]])\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { pipe, splitEvery } from 'rambda'\n\nconst list = [1, 2, 3, 4, 5, 6, 7]\n\ndescribe('R.splitEvery', () =\u003e {\n  it('happy', () =\u003e {\n    const result = pipe(list, splitEvery(3))\n    result // $ExpectType number[][]\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#splitEvery)\n\n### symmetricDifference\n\n```typescript\n\nsymmetricDifference\u003cT\u003e(x: T[]): \u003cT\u003e(y: T[]) =\u003e T[]\n```\n\nIt returns a merged list of `x` and `y` with all equal elements removed.\n\n`R.equals` is used to determine equality.\n\n```javascript\nconst x = [ 1, 2, 3, 4 ]\nconst y = [ 3, 4, 5, 6 ]\n\nconst result = R.symmetricDifference(x, y)\n// =\u003e [ 1, 2, 5, 6 ]\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20x%20%3D%20%5B%201%2C%202%2C%203%2C%204%20%5D%0Aconst%20y%20%3D%20%5B%203%2C%204%2C%205%2C%206%20%5D%0A%0Aconst%20result%20%3D%20R.symmetricDifference(x%2C%20y)%0A%2F%2F%20%3D%3E%20%5B%201%2C%202%2C%205%2C%206%20%5D\"\u003eTry this \u003cstrong\u003eR.symmetricDifference\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nsymmetricDifference\u003cT\u003e(x: T[]): \u003cT\u003e(y: T[]) =\u003e T[];\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.symmetricDifference\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nimport { filter } from './filter.js'\nimport { includes } from './includes.js'\n\nexport function symmetricDifference(x) {\n  return y =\u003e [\n    ...filter(value =\u003e !includes(value)(y))(x),\n    ...filter(value =\u003e !includes(value)(x))(y),\n  ]\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { symmetricDifference } from './symmetricDifference.js'\n\ntest('symmetricDifference', () =\u003e {\n  const list1 = [1, 2, 3, 4]\n  const list2 = [3, 4, 5, 6]\n  expect(symmetricDifference(list1)(list2)).toEqual([1, 2, 5, 6])\n  expect(symmetricDifference([])([])).toEqual([])\n})\n\ntest('symmetricDifference with objects', () =\u003e {\n  const list1 = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }]\n  const list2 = [{ id: 3 }, { id: 4 }, { id: 5 }, { id: 6 }]\n  expect(symmetricDifference(list1)(list2)).toEqual([\n    { id: 1 },\n    { id: 2 },\n    { id: 5 },\n    { id: 6 },\n  ])\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { symmetricDifference } from 'rambda'\n\ndescribe('R.symmetricDifference', () =\u003e {\n  it('happy', () =\u003e {\n    const list1 = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }]\n    const list2 = [{ id: 3 }, { id: 4 }, { id: 5 }, { id: 6 }]\n    const result = symmetricDifference(list1)(list2)\n\n    result // $ExpectType { id: number; }[]\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#symmetricDifference)\n\n### tail\n\n```typescript\n\ntail\u003cT extends unknown[]\u003e(input: T): T extends [any, ...infer U] ? U : [...T]\n```\n\nIt returns all but the first element of `input`.\n\n```javascript\nconst result = [\n  R.tail([1, 2, 3]),  \n  R.tail('foo') \n]\n// =\u003e [[2, 3], 'oo']\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20result%20%3D%20%5B%0A%20%20R.tail(%5B1%2C%202%2C%203%5D)%2C%20%20%0A%20%20R.tail('foo')%20%0A%5D%0A%2F%2F%20%3D%3E%20%5B%5B2%2C%203%5D%2C%20'oo'%5D\"\u003eTry this \u003cstrong\u003eR.tail\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\ntail\u003cT extends unknown[]\u003e(input: T): T extends [any, ...infer U] ? U : [...T];\ntail(input: string): string;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.tail\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nimport { drop } from './drop.js'\n\nexport function tail(listOrString) {\n  return drop(1)(listOrString)\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { tail } from './tail.js'\n\ntest('tail', () =\u003e {\n  expect(tail([1, 2, 3])).toEqual([2, 3])\n  expect(tail([1, 2])).toEqual([2])\n  expect(tail([1])).toEqual([])\n  expect(tail([])).toEqual([])\n\n  expect(tail('abc')).toBe('bc')\n  expect(tail('ab')).toBe('b')\n  expect(tail('a')).toBe('')\n  expect(tail('')).toBe('')\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { tail } from 'rambda'\n\ndescribe('R.tail', () =\u003e {\n  it('with string', () =\u003e {\n    const result = tail('foo')\n\n    result // $ExpectType string\n  })\n  it('with list - one type', () =\u003e {\n    const result = tail([1, 2, 3])\n\n    result // $ExpectType number[]\n  })\n  it('with list - mixed types', () =\u003e {\n    const result = tail(['foo', 'bar', 1, 2, 3])\n\n    result // $ExpectType (string | number)[]\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#tail)\n\n### take\n\n```typescript\n\ntake\u003cT\u003e(howMany: number): {\n  (input: string): string\n```\n\nIt returns the first `howMany` elements of `input`.\n\n```javascript\nconst howMany = 2\n\nconst result = [\n  R.take(howMany)([1, 2, 3]),\n  R.take(howMany, 'foobar'),\n]\n// =\u003e [[1, 2], 'fo']\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20howMany%20%3D%202%0A%0Aconst%20result%20%3D%20%5B%0A%20%20R.take(howMany)(%5B1%2C%202%2C%203%5D)%2C%0A%20%20R.take(howMany%2C%20'foobar')%2C%0A%5D%0A%2F%2F%20%3D%3E%20%5B%5B1%2C%202%5D%2C%20'fo'%5D\"\u003eTry this \u003cstrong\u003eR.take\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\ntake\u003cT\u003e(howMany: number): {\n  (input: string): string;\n  (input: T[]): T[];\n  (input: readonly T[]): T[];\n};\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.take\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nimport { baseSlice } from './_internals/baseSlice.js'\n\nexport function take(numberOfItems) {\n  return input =\u003e {\n    if (numberOfItems \u003c 0) {\n      return input.slice()\n    }\n    if (typeof input === 'string') {\n      return input.slice(0, numberOfItems)\n    }\n\n    return baseSlice(input, 0, numberOfItems)\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { take } from './take.js'\n\ntest('happy', () =\u003e {\n  const arr = ['foo', 'bar', 'baz']\n\n  expect(take(1)(arr)).toEqual(['foo'])\n  expect(arr).toEqual(['foo', 'bar', 'baz'])\n  expect(take(2)(['foo', 'bar', 'baz'])).toEqual(['foo', 'bar'])\n  expect(take(3)(['foo', 'bar', 'baz'])).toEqual(['foo', 'bar', 'baz'])\n  expect(take(4)(['foo', 'bar', 'baz'])).toEqual(['foo', 'bar', 'baz'])\n  expect(take(3)('rambda')).toBe('ram')\n})\n\ntest('with negative index', () =\u003e {\n  expect(take(-1)([1, 2, 3])).toEqual([1, 2, 3])\n  expect(take(Number.NEGATIVE_INFINITY)([1, 2, 3])).toEqual([1, 2, 3])\n})\n\ntest('with zero index', () =\u003e {\n  expect(take(0)([1, 2, 3])).toEqual([])\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#take)\n\n### takeLast\n\n```typescript\n\ntakeLast\u003cT\u003e(howMany: number): {\n  (input: string): string\n```\n\nIt returns the last `howMany` elements of `input`.\n\n```javascript\nconst howMany = 2\n\nconst result = [\n  R.takeLast(howMany)([1, 2, 3]),\n  R.takeLast(howMany)('foobar'),\n]\n// =\u003e [[2, 3], 'ar']\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20howMany%20%3D%202%0A%0Aconst%20result%20%3D%20%5B%0A%20%20R.takeLast(howMany)(%5B1%2C%202%2C%203%5D)%2C%0A%20%20R.takeLast(howMany)('foobar')%2C%0A%5D%0A%2F%2F%20%3D%3E%20%5B%5B2%2C%203%5D%2C%20'ar'%5D\"\u003eTry this \u003cstrong\u003eR.takeLast\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\ntakeLast\u003cT\u003e(howMany: number): {\n  (input: string): string;\n  (input: T[]): T[];\n  (input: readonly T[]): T[];\n};\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.takeLast\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nimport { baseSlice } from './_internals/baseSlice.js'\n\nexport function takeLast(numberOfItems) {\n  return input =\u003e {\n    const len = input.length\n    if (numberOfItems \u003c 0) {\n      return input.slice()\n    }\n    let numValue = numberOfItems \u003e len ? len : numberOfItems\n\n    if (typeof input === 'string') {\n      return input.slice(len - numValue)\n    }\n\n    numValue = len - numValue\n\n    return baseSlice(input, numValue, len)\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { takeLast } from './takeLast.js'\n\ntest('with arrays', () =\u003e {\n  expect(takeLast(1)(['foo', 'bar', 'baz'])).toEqual(['baz'])\n  expect(takeLast(2)(['foo', 'bar', 'baz'])).toEqual(['bar', 'baz'])\n  expect(takeLast(3)(['foo', 'bar', 'baz'])).toEqual(['foo', 'bar', 'baz'])\n  expect(takeLast(4)(['foo', 'bar', 'baz'])).toEqual(['foo', 'bar', 'baz'])\n  expect(takeLast(10)(['foo', 'bar', 'baz'])).toEqual(['foo', 'bar', 'baz'])\n})\n\ntest('with strings', () =\u003e {\n  expect(takeLast(3)('rambda')).toBe('bda')\n  expect(takeLast(7)('rambda')).toBe('rambda')\n})\n\ntest('with negative index', () =\u003e {\n  expect(takeLast(-1)([1, 2, 3])).toEqual([1, 2, 3])\n  expect(takeLast(Number.NEGATIVE_INFINITY)([1, 2, 3])).toEqual([1, 2, 3])\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#takeLast)\n\n### takeLastWhile\n\n```typescript\n\ntakeLastWhile\u003cT\u003e(predicate: (x: T) =\u003e boolean): (input: T[]) =\u003e T[]\n```\n\n```javascript\nconst result = R.takeLastWhile(x =\u003e x \u003e 2)([1, 2, 3, 4])\n// =\u003e [3, 4]\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20result%20%3D%20R.takeLastWhile(x%20%3D%3E%20x%20%3E%202)(%5B1%2C%202%2C%203%2C%204%5D)%0A%2F%2F%20%3D%3E%20%5B3%2C%204%5D\"\u003eTry this \u003cstrong\u003eR.takeLastWhile\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\ntakeLastWhile\u003cT\u003e(predicate: (x: T) =\u003e boolean): (input: T[]) =\u003e T[];\ntakeLastWhile\u003cT\u003e(predicate: (x: T, index: number) =\u003e boolean): (list: T[]) =\u003e T[];\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.takeLastWhile\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function takeLastWhile(predicate) {\n  return input =\u003e {\n    if (input.length === 0) {\n      return input\n    }\n\n    const toReturn = []\n    let counter = input.length\n\n    while (counter) {\n      const item = input[--counter]\n      if (!predicate(item)) {\n        break\n      }\n      toReturn.push(item)\n    }\n\n    return toReturn.reverse()\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { takeLastWhile } from './takeLastWhile.js'\n\nconst list = [1, 2, 3, 4]\n\ntest('happy', () =\u003e {\n  const predicate = x =\u003e x \u003e 2\n  const result = takeLastWhile(predicate)(list)\n  expect(result).toEqual([3, 4])\n})\n\ntest('predicate is always true', () =\u003e {\n  const predicate = () =\u003e true\n  const result = takeLastWhile(predicate)(list)\n  expect(result).toEqual(list)\n})\n\ntest('predicate is always false', () =\u003e {\n  const predicate = () =\u003e false\n  const result = takeLastWhile(predicate)(list)\n  expect(result).toEqual([])\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#takeLastWhile)\n\n### takeWhile\n\n```javascript\nconst list = [1, 2, 3, 4]\nconst predicate = x =\u003e x \u003c 3\n\nconst result = R.takeWhile(predicate)(list)\n// =\u003e [1, 2]\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20list%20%3D%20%5B1%2C%202%2C%203%2C%204%5D%0Aconst%20predicate%20%3D%20x%20%3D%3E%20x%20%3C%203%0A%0Aconst%20result%20%3D%20R.takeWhile(predicate)(list)%0A%2F%2F%20%3D%3E%20%5B1%2C%202%5D\"\u003eTry this \u003cstrong\u003eR.takeWhile\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#takeWhile)\n\n### tap\n\n```typescript\n\ntap\u003cT\u003e(fn: (x: T) =\u003e void): (input: T) =\u003e T\n```\n\nIt applies function `fn` to input `x` and returns `x`. \n\nOne use case is debugging in the middle of `R.pipe` chain.\n\n```javascript\nconst list = [1, 2, 3]\n\nR.pipe(\n\tlist,\n  R.map(x =\u003e x * 2)\n  R.tap(console.log),\n  R.filter(x =\u003e x \u003e 1)\n)\n// =\u003e `2` and `3` will be logged\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20list%20%3D%20%5B1%2C%202%2C%203%5D%0A%0AR.pipe(%0A%09list%2C%0A%20%20R.map(x%20%3D%3E%20x%20*%202)%0A%20%20R.tap(console.log)%2C%0A%20%20R.filter(x%20%3D%3E%20x%20%3E%201)%0A)%0A%2F%2F%20%3D%3E%20%602%60%20and%20%603%60%20will%20be%20logged\"\u003eTry this \u003cstrong\u003eR.tap\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\ntap\u003cT\u003e(fn: (x: T) =\u003e void): (input: T) =\u003e T;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.tap\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function tap(fn) {\n  return x =\u003e {\n    fn(x)\n\n    return x\n  }\n}\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#tap)\n\n### test\n\n```typescript\n\ntest(regExpression: RegExp): (str: string) =\u003e boolean\n```\n\nIt determines whether `str` matches `regExpression`.\n\n```javascript\nR.test(/^f/)('foo')\n// =\u003e true\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20result%20%3D%20R.test(%2F%5Ef%2F)('foo')%0A%2F%2F%20%3D%3E%20true\"\u003eTry this \u003cstrong\u003eR.test\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\ntest(regExpression: RegExp): (str: string) =\u003e boolean;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.test\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function test(pattern) {\n  return str =\u003e str.search(pattern) !== -1\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { test as testMethod } from './test.js'\n\ntest('happy', () =\u003e {\n  expect(testMethod(/^x/)('xyz')).toBeTruthy()\n  expect(testMethod(/^y/)('xyz')).toBeFalsy()\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { test } from 'rambda'\n\nconst input = 'foo   '\nconst regex = /foo/\n\nit('R.test', () =\u003e {\n  const result = test(regex)(input)\n\n  result // $ExpectType boolean\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#test)\n\n### tryCatch\n\nIt returns function that runs `fn` in `try/catch` block. If there was an error, then `fallback` is used to return the result.\n\n```javascript\nconst fn = x =\u003e x.foo\n\nconst result = [\n  R.tryCatch(fn, false)(null),\n  R.tryCatch(fn, false)({foo: 'bar'})\n]\n// =\u003e [false, 'bar']\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20fn%20%3D%20x%20%3D%3E%20x.foo%0A%0Aconst%20result%20%3D%20%5B%0A%20%20R.tryCatch(fn%2C%20false)(null)%2C%0A%20%20R.tryCatch(fn%2C%20false)(%7Bfoo%3A%20'bar'%7D)%0A%5D%0A%2F%2F%20%3D%3E%20%5Bfalse%2C%20'bar'%5D\"\u003eTry this \u003cstrong\u003eR.tryCatch\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#tryCatch)\n\n### type\n\nIt accepts any input and it returns its type.\n\n\u003e :boom: `NaN`, `Promise` and `Async` are types specific for **Rambda**.\n\n```javascript\nconst result = R.type(() =\u003e {}) // =\u003e 'Function'\nR.type(async () =\u003e {}) // =\u003e 'Async'\nR.type([]) // =\u003e 'Array'\nR.type({}) // =\u003e 'Object'\nR.type('foo') // =\u003e 'String'\nR.type(1) // =\u003e 'Number'\nR.type(true) // =\u003e 'Boolean'\nR.type(null) // =\u003e 'Null'\nR.type(/[A-z]/) // =\u003e 'RegExp'\nR.type('foo'*1) // =\u003e 'NaN'\n\nconst delay = ms =\u003e new Promise(resolve =\u003e {\n  setTimeout(function () {\n    resolve()\n  }, ms)\n})\nR.type(delay) // =\u003e 'Promise'\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20result%20%3D%20R.type(()%20%3D%3E%20%7B%7D)%20%2F%2F%20%3D%3E%20'Function'%0AR.type(async%20()%20%3D%3E%20%7B%7D)%20%2F%2F%20%3D%3E%20'Async'%0AR.type(%5B%5D)%20%2F%2F%20%3D%3E%20'Array'%0AR.type(%7B%7D)%20%2F%2F%20%3D%3E%20'Object'%0AR.type('foo')%20%2F%2F%20%3D%3E%20'String'%0AR.type(1)%20%2F%2F%20%3D%3E%20'Number'%0AR.type(true)%20%2F%2F%20%3D%3E%20'Boolean'%0AR.type(null)%20%2F%2F%20%3D%3E%20'Null'%0AR.type(%2F%5BA-z%5D%2F)%20%2F%2F%20%3D%3E%20'RegExp'%0AR.type('foo'*1)%20%2F%2F%20%3D%3E%20'NaN'%0A%0Aconst%20delay%20%3D%20ms%20%3D%3E%20new%20Promise(resolve%20%3D%3E%20%7B%0A%20%20setTimeout(function%20()%20%7B%0A%20%20%20%20resolve()%0A%20%20%7D%2C%20ms)%0A%7D)%0AR.type(delay)%20%2F%2F%20%3D%3E%20'Promise'\"\u003eTry this \u003cstrong\u003eR.type\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#type)\n\n### union\n\n```typescript\n\nunion\u003cT\u003e(x: T[]): (y: T[]) =\u003e T[]\n```\n\nIt takes two lists and return a new list containing a merger of both list with removed duplicates. \n\n`R.equals` is used to compare for duplication.\n\n```javascript\nconst result = R.union([1,2,3], [3,4,5]);\n// =\u003e [1, 2, 3, 4, 5]\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20result%20%3D%20R.union(%5B1%2C2%2C3%5D%2C%20%5B3%2C4%2C5%5D)%3B%0A%2F%2F%20%3D%3E%20%5B1%2C%202%2C%203%2C%204%2C%205%5D\"\u003eTry this \u003cstrong\u003eR.union\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nunion\u003cT\u003e(x: T[]): (y: T[]) =\u003e T[];\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.union\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nimport { cloneList } from './_internals/cloneList.js'\nimport { includes } from './includes.js'\n\nexport function union(x) {\n  return y =\u003e {\n    const toReturn = cloneList(x)\n\n    y.forEach(yInstance =\u003e {\n      if (!includes(yInstance)(x)) {\n        toReturn.push(yInstance)\n      }\n    })\n\n    return toReturn\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { union } from './union.js'\n\ntest('happy', () =\u003e {\n  expect(union([1, 2])([2, 3])).toEqual([1, 2, 3])\n})\n\ntest('with list of objects', () =\u003e {\n  const list1 = [{ a: 1 }, { a: 2 }]\n  const list2 = [{ a: 2 }, { a: 3 }]\n  const result = union(list1)(list2)\n  expect(result).toEqual([{ a: 1 }, { a: 2 }, { a: 3 }])\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { union } from 'rambda'\n\ndescribe('R.union', () =\u003e {\n  it('happy', () =\u003e {\n    const result = union([1, 2])([2, 3])\n\n    result // $ExpectType number[]\n  })\n  it('with array of objects - case 1', () =\u003e {\n    const list1 = [{ a: 1 }, { a: 2 }]\n    const list2 = [{ a: 2 }, { a: 3 }]\n    const result = union(list1)(list2)\n    result // $ExpectType { a: number; }[]\n  })\n  it('with array of objects - case 2', () =\u003e {\n    const list1 = [{ a: 1, b: 1 }, { a: 2 }]\n    const list2 = [{ a: 2 }, { a: 3, b: 3 }]\n    const result = union(list1)(list2)\n    result[0].a // $ExpectType number\n    result[0].b // $ExpectType number | undefined\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#union)\n\n### uniq\n\n```typescript\n\nuniq\u003cT\u003e(list: T[]): T[]\n```\n\nIt returns a new array containing only one copy of each element of `list`.\n\n`R.equals` is used to determine equality.\n\n```javascript\nconst list = [1, 1, {a: 1}, {a: 2}, {a:1}]\n\nR.uniq(list)\n// =\u003e [1, {a: 1}, {a: 2}]\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20list%20%3D%20%5B1%2C%201%2C%20%7Ba%3A%201%7D%2C%20%7Ba%3A%202%7D%2C%20%7Ba%3A1%7D%5D%0A%0Aconst%20result%20%3D%20R.uniq(list)%0A%2F%2F%20%3D%3E%20%5B1%2C%20%7Ba%3A%201%7D%2C%20%7Ba%3A%202%7D%5D\"\u003eTry this \u003cstrong\u003eR.uniq\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nuniq\u003cT\u003e(list: T[]): T[];\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.uniq\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nimport { _Set } from './_internals/set.js'\n\nexport function uniq(list) {\n  const set = new _Set()\n  const willReturn = []\n  list.forEach(item =\u003e {\n    if (set.checkUniqueness(item)) {\n      willReturn.push(item)\n    }\n  })\n\n  return willReturn\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { uniq } from './uniq.js'\n\ntest('happy', () =\u003e {\n  const list = [1, 2, 3, 3, 3, 1, 2, 0]\n  expect(uniq(list)).toEqual([1, 2, 3, 0])\n})\n\ntest('with object', () =\u003e {\n  const list = [{ a: 1 }, { a: 2 }, { a: 1 }, { a: 2 }]\n  expect(uniq(list)).toEqual([{ a: 1 }, { a: 2 }])\n})\n\ntest('with nested array', () =\u003e {\n  expect(uniq([[42], [42]])).toEqual([[42]])\n})\n\ntest('with booleans', () =\u003e {\n  expect(uniq([[false], [false], [true]])).toEqual([[false], [true]])\n})\n\ntest('with falsy values', () =\u003e {\n  expect(uniq([undefined, null])).toEqual([undefined, null])\n})\n\ntest('can distinct between string and number', () =\u003e {\n  expect(uniq([1, '1'])).toEqual([1, '1'])\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { uniq } from 'rambda'\n\ndescribe('R.uniq', () =\u003e {\n  it('happy', () =\u003e {\n    const result = uniq([1, 2, 3, 3, 3, 1, 2, 0])\n    result // $ExpectType number[]\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#uniq)\n\n### uniqBy\n\nIt applies uniqueness to input list based on function that defines what to be used for comparison between elements.\n\n`R.equals` is used to determine equality.\n\n```javascript\nconst list = [{a:1}, {a:2}, {a:1}]\nconst result = R.uniqBy(x =\u003e x, list)\n\n// =\u003e [{a:1}, {a:2}]\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20list%20%3D%20%5B%7Ba%3A1%7D%2C%20%7Ba%3A2%7D%2C%20%7Ba%3A1%7D%5D%0Aconst%20result%20%3D%20R.uniqBy(x%20%3D%3E%20x%2C%20list)%0A%0A%2F%2F%20%3D%3E%20%5B%7Ba%3A1%7D%2C%20%7Ba%3A2%7D%5D\"\u003eTry this \u003cstrong\u003eR.uniqBy\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#uniqBy)\n\n### uniqWith\n\n```typescript\n\nuniqWith\u003cT\u003e(predicate: (x: T, y: T) =\u003e boolean): (list: T[]) =\u003e T[]\n```\n\nIt returns a new array containing only one copy of each element in `list` according to `predicate` function.\n\nThis predicate should return true, if two elements are equal.\n\n```javascript\nconst list = [\n  {id: 0, title:'foo'},\n  {id: 1, title:'bar'},\n  {id: 2, title:'baz'},\n  {id: 3, title:'foo'},\n  {id: 4, title:'bar'},\n]\n\nconst expected = [\n  {id: 0, title:'foo'},\n  {id: 1, title:'bar'},\n  {id: 2, title:'baz'},\n]\n\nconst predicate = (x,y) =\u003e x.title === y.title\n\nconst result = R.uniqWith(predicate)(list)\n// =\u003e `result` is equal to `expected`\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20list%20%3D%20%5B%0A%20%20%7Bid%3A%200%2C%20title%3A'foo'%7D%2C%0A%20%20%7Bid%3A%201%2C%20title%3A'bar'%7D%2C%0A%20%20%7Bid%3A%202%2C%20title%3A'baz'%7D%2C%0A%20%20%7Bid%3A%203%2C%20title%3A'foo'%7D%2C%0A%20%20%7Bid%3A%204%2C%20title%3A'bar'%7D%2C%0A%5D%0A%0Aconst%20expected%20%3D%20%5B%0A%20%20%7Bid%3A%200%2C%20title%3A'foo'%7D%2C%0A%20%20%7Bid%3A%201%2C%20title%3A'bar'%7D%2C%0A%20%20%7Bid%3A%202%2C%20title%3A'baz'%7D%2C%0A%5D%0A%0Aconst%20predicate%20%3D%20(x%2Cy)%20%3D%3E%20x.title%20%3D%3D%3D%20y.title%0A%0Aconst%20result%20%3D%20R.uniqWith(predicate)(list)%0A%2F%2F%20%3D%3E%20%60result%60%20is%20equal%20to%20%60expected%60\"\u003eTry this \u003cstrong\u003eR.uniqWith\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nuniqWith\u003cT\u003e(predicate: (x: T, y: T) =\u003e boolean): (list: T[]) =\u003e T[];\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.uniqWith\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nfunction includesWith(predicate, target, list) {\n  let willReturn = false\n  let index = -1\n\n  while (++index \u003c list.length \u0026\u0026 !willReturn) {\n    const value = list[index]\n\n    if (predicate(target, value)) {\n      willReturn = true\n    }\n  }\n\n  return willReturn\n}\n\nexport function uniqWith(predicate) {\n  return list =\u003e {\n    let index = -1\n    const willReturn = []\n\n    while (++index \u003c list.length) {\n      const value = list[index]\n\n      if (!includesWith(predicate, value, willReturn)) {\n        willReturn.push(value)\n      }\n    }\n\n    return willReturn\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { uniqWith } from './uniqWith.js'\n\nconst list = [{ a: 1 }, { a: 1 }]\n\ntest('happy', () =\u003e {\n  const fn = (x, y) =\u003e x.a === y.a\n\n  const result = uniqWith(fn)(list)\n  expect(result).toEqual([{ a: 1 }])\n})\n\ntest('with list of strings', () =\u003e {\n  const fn = (x, y) =\u003e x.length === y.length\n  const list = ['0', '11', '222', '33', '4', '55']\n  const result = uniqWith(fn)(list)\n  expect(result).toEqual(['0', '11', '222'])\n})\n\ntest('should return items that are not equal to themselves', () =\u003e {\n  // test case based on https://github.com/remeda/remeda/issues/999\n  const data = [\n    { id: 1, reason: 'No name' },\n    { id: 1, reason: 'No name' },\n    { reason: 'No name' },\n    { reason: 'No name' },\n  ]\n  const expectedResult = [\n    { id: 1, reason: 'No name' },\n    { reason: 'No name' },\n    { reason: 'No name' },\n  ]\n\n  const result = uniqWith((errorA, errorB) =\u003e {\n    // the objects with no ids should effectively be ignored from removal of duplicates\n    if (errorA.id === undefined || errorB.id === undefined) {\n      return false\n    }\n    return errorA.id === errorB.id\n  })(data)\n\n  expect(result).toEqual(expectedResult)\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { pipe, uniqWith } from 'rambda'\n\ndescribe('R.uniqWith', () =\u003e {\n  it('happy', () =\u003e {\n    const result = pipe(\n      [{ a: 1 }, { a: 1 }],\n      uniqWith((x, y) =\u003e x.a === y.a),\n    )\n    result // $ExpectType { a: number; }[]\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#uniqWith)\n\n### unless\n\n```typescript\n\nunless\u003cT, U\u003e(predicate: (x: T) =\u003e boolean, whenFalseFn: (x: T) =\u003e U): (x: T) =\u003e T | U\n```\n\nThe method returns function that will be called with argument `input`.\n\nIf `predicate(input)` returns `false`, then the end result will be the outcome of `whenFalse(input)`.\n\nIn the other case, the final output will be the `input` itself.\n\n```javascript\nconst fn = R.unless(\n  x =\u003e x \u003e 2,\n  x =\u003e x + 10\n)\n\nconst result = [\n  fn(1),\n  fn(5)\n]\n// =\u003e [11, 5]\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20fn%20%3D%20R.unless(%0A%20%20x%20%3D%3E%20x%20%3E%202%2C%0A%20%20x%20%3D%3E%20x%20%2B%2010%0A)%0A%0Aconst%20result%20%3D%20%5B%0A%20%20fn(1)%2C%0A%20%20fn(5)%0A%5D%0A%2F%2F%20%3D%3E%20%5B11%2C%205%5D\"\u003eTry this \u003cstrong\u003eR.unless\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nunless\u003cT, U\u003e(predicate: (x: T) =\u003e boolean, whenFalseFn: (x: T) =\u003e U): (x: T) =\u003e T | U;\nunless\u003cT\u003e(predicate: (x: T) =\u003e boolean, whenFalseFn: (x: T) =\u003e T): (x: T) =\u003e T;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.unless\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function unless(predicate, whenFalseFn) {\n  return input =\u003e {\n    if (predicate(input)) {\n      return input\n    }\n\n    return whenFalseFn(input)\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { unless } from './unless.js'\n\ntest('happy', () =\u003e {\n  expect(\n    unless(\n      x =\u003e x \u003e 10,\n      x =\u003e x + 1,\n    )(20),\n  ).toEqual(20)\n  expect(\n    unless(\n      x =\u003e x \u003e 10,\n      x =\u003e x + 1,\n    )(5),\n  ).toEqual(6)\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { pipe, unless } from 'rambda'\n\nconst inc = (x: number) =\u003e x + 1\n\ndescribe('R.unless', () =\u003e {\n  it('happy', () =\u003e {\n    const result = pipe(\n      1,\n      unless(x =\u003e x \u003e 5, inc),\n    )\n    result // $ExpectType number\n  })\n  it('with two different types', () =\u003e {\n    const result = pipe(\n      1,\n      unless(\n        x =\u003e {\n          x // $ExpectType number\n          return x \u003e 5\n        },\n        x =\u003e {\n          x // $ExpectType number\n          return `${x}-foo`\n        },\n      ),\n    )\n    result // $ExpectType string | number\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#unless)\n\n### unwind\n\nIt takes an object and a property name. The method will return a list of objects, where each object is a shallow copy of the input object, but with the property array unwound.\n\n```javascript\nconst obj = {\n  a: 1,\n  b: [2, 3],\n}\nconst result = R.unwind('b')(obj)\nconst expected = [{a:1, b:2}, {a:1, b:3}]\n// =\u003e `result` is equal to `expected`\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20obj%20%3D%20%7B%0A%20%20a%3A%201%2C%0A%20%20b%3A%20%5B2%2C%203%5D%2C%0A%7D%0Aconst%20result%20%3D%20R.unwind('b')(obj)%0Aconst%20expected%20%3D%20%5B%7Ba%3A1%2C%20b%3A2%7D%2C%20%7Ba%3A1%2C%20b%3A3%7D%5D%0A%2F%2F%20%3D%3E%20%60result%60%20is%20equal%20to%20%60expected%60\"\u003eTry this \u003cstrong\u003eR.unwind\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#unwind)\n\n### update\n\n```typescript\n\nupdate\u003cT\u003e(index: number, newValue: T): (list: T[]) =\u003e T[]\n```\n\nIt returns a copy of `list` with updated element at `index` with `newValue`.\n\n```javascript\nconst index = 2\nconst newValue = 88\nconst list = [1, 2, 3, 4, 5]\n\nconst result = R.update(index, newValue, list)\n// =\u003e [1, 2, 88, 4, 5]\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20index%20%3D%202%0Aconst%20newValue%20%3D%2088%0Aconst%20list%20%3D%20%5B1%2C%202%2C%203%2C%204%2C%205%5D%0A%0Aconst%20result%20%3D%20R.update(index%2C%20newValue%2C%20list)%0A%2F%2F%20%3D%3E%20%5B1%2C%202%2C%2088%2C%204%2C%205%5D\"\u003eTry this \u003cstrong\u003eR.update\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nupdate\u003cT\u003e(index: number, newValue: T): (list: T[]) =\u003e T[];\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.update\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nimport { cloneList } from './_internals/cloneList.js'\n\nexport function update(index, newValue) {\n  return list =\u003e {\n    const clone = cloneList(list)\n    if (index === -1) {\n      return clone.fill(newValue, index)\n    }\n\n    return clone.fill(newValue, index, index + 1)\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { update } from './update.js'\n\nconst list = [1, 2, 3]\n\ntest('happy', () =\u003e {\n  const newValue = 8\n  const index = 1\n  const result = update(index, newValue)(list)\n\n  const expected = [1, 8, 3]\n  expect(result).toEqual(expected)\n})\n\ntest('list has no such index', () =\u003e {\n  const newValue = 8\n  const index = 10\n  const result = update(index, newValue)(list)\n\n  expect(result).toEqual(list)\n})\n\ntest('with negative index', () =\u003e {\n  expect(update(-1, 10)([1])).toEqual([10])\n  expect(update(-1, 10)([])).toEqual([])\n  expect(update(-1, 10)(list)).toEqual([1, 2, 10])\n  expect(update(-2, 10)(list)).toEqual([1, 10, 3])\n  expect(update(-3, 10)(list)).toEqual([10, 2, 3])\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#update)\n\n### when\n\n```typescript\n\nwhen\u003cT\u003e(predicate: (x: T) =\u003e boolean, whenTrueFn: (x: T) =\u003e T): (input: T) =\u003e T\n```\n\nIt pass `input` to `predicate` function and if the result is `true`, it will return the result of `whenTrueFn(input)`. \nIf the `predicate` returns `false`, then it will simply return `input`.\n\n```javascript\nconst predicate = x =\u003e typeof x === 'number'\nconst whenTrueFn = R.add(11)\n\nconst fn = when(predicate, whenTrueResult)\n\nconst positiveInput = 88\nconst negativeInput = 'foo'\n\nconst result = [\n  fn(positiveInput),\n  fn(positiveInput),\n]\n\nconst expected = [\n  99,\n  'foo',\n]\n// =\u003e `result` is equal to `expected`\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20predicate%20%3D%20x%20%3D%3E%20typeof%20x%20%3D%3D%3D%20'number'%0Aconst%20whenTrueFn%20%3D%20R.add(11)%0A%0Aconst%20fn%20%3D%20when(predicate%2C%20whenTrueResult)%0A%0Aconst%20positiveInput%20%3D%2088%0Aconst%20negativeInput%20%3D%20'foo'%0A%0Aconst%20result%20%3D%20%5B%0A%20%20fn(positiveInput)%2C%0A%20%20fn(positiveInput)%2C%0A%5D%0A%0Aconst%20expected%20%3D%20%5B%0A%20%2099%2C%0A%20%20'foo'%2C%0A%5D%0A%2F%2F%20%3D%3E%20%60result%60%20is%20equal%20to%20%60expected%60\"\u003eTry this \u003cstrong\u003eR.when\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nwhen\u003cT\u003e(predicate: (x: T) =\u003e boolean, whenTrueFn: (x: T) =\u003e T): (input: T) =\u003e T;\nwhen\u003cT, U\u003e(predicate: (x: T) =\u003e boolean, whenTrueFn: (x: T) =\u003e U): (input: T) =\u003e T | U;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.when\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function when(predicate, whenTrueFn) {\n  return input =\u003e {\n    if (!predicate(input)) {\n      return input\n    }\n\n    return whenTrueFn(input)\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { when } from './when.js'\n\nconst predicate = x =\u003e typeof x === 'number'\n\ntest('happy', () =\u003e {\n  const fn = when(predicate, x =\u003e x + 1)\n  expect(fn(11)).toBe(12)\n  expect(fn('foo')).toBe('foo')\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { pipe, tap, when } from 'rambda'\n\ndescribe('R.when', () =\u003e {\n  it('happy', () =\u003e {\n    const result = pipe(\n      1,\n      when(\n        x =\u003e x \u003e 2,\n        x =\u003e x,\n      ),\n      tap(x =\u003e {\n        x // $ExpectType number\n      }),\n      when(\n        x =\u003e x \u003e 2,\n        x =\u003e String(x),\n      ),\n    )\n\n    result // $ExpectType string | number\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#when)\n\n### zip\n\n```typescript\n\nzip\u003cK\u003e(x: K[]): \u003cV\u003e(y: V[]) =\u003e KeyValuePair\u003cK, V\u003e[]\n```\n\nIt will return a new array containing tuples of equally positions items from both `x` and `y` lists. \n\nThe returned list will be truncated to match the length of the shortest supplied list.\n\n```javascript\nconst x = [1, 2]\nconst y = ['A', 'B']\nR.zip(x)(y)\n// =\u003e [[1, 'A'], [2, 'B']]\n\n// truncates to shortest list\nR.zip([...x, 3])(['A', 'B'])\n// =\u003e [[1, 'A'], [2, 'B']]\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20x%20%3D%20%5B1%2C%202%5D%0Aconst%20y%20%3D%20%5B'A'%2C%20'B'%5D%0AR.zip(x)(y)%0A%2F%2F%20%3D%3E%20%5B%5B1%2C%20'A'%5D%2C%20%5B2%2C%20'B'%5D%5D%0A%0A%2F%2F%20truncates%20to%20shortest%20list%0Aconst%20result%20%3D%20R.zip(%5B...x%2C%203%5D)(%5B'A'%2C%20'B'%5D)%0A%2F%2F%20%3D%3E%20%5B%5B1%2C%20'A'%5D%2C%20%5B2%2C%20'B'%5D%5D\"\u003eTry this \u003cstrong\u003eR.zip\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nzip\u003cK\u003e(x: K[]): \u003cV\u003e(y: V[]) =\u003e KeyValuePair\u003cK, V\u003e[];\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.zip\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nexport function zip(left) {\n  return right =\u003e {\n    const result = []\n    const length = Math.min(left.length, right.length)\n\n    for (let i = 0; i \u003c length; i++) {\n      result[i] = [left[i], right[i]]\n    }\n\n    return result\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { zip } from './zip.js'\n\nconst array1 = [1, 2, 3]\nconst array2 = ['A', 'B', 'C']\n\ntest('should return an array', () =\u003e {\n  const actual = zip(array1)(array2)\n  expect(actual).toBeInstanceOf(Array)\n})\n\ntest('should return and array or tuples', () =\u003e {\n  const expected = [\n    [1, 'A'],\n    [2, 'B'],\n    [3, 'C'],\n  ]\n  const actual = zip(array1)(array2)\n  expect(actual).toEqual(expected)\n})\n\ntest('should truncate result to length of shorted input list', () =\u003e {\n  const expectedA = [\n    [1, 'A'],\n    [2, 'B'],\n  ]\n  const actualA = zip([1, 2])(array2)\n  expect(actualA).toEqual(expectedA)\n\n  const expectedB = [\n    [1, 'A'],\n    [2, 'B'],\n  ]\n  const actualB = zip(array1)(['A', 'B'])\n  expect(actualB).toEqual(expectedB)\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { zip } from 'rambda'\n\ndescribe('R.zip', () =\u003e {\n  it('happy', () =\u003e {\n    const array1 = [1, 2, 3]\n    const array2 = ['A', 'B', 'C']\n    let a: Partial\u003cany\u003e\n    const result = zip(array1)(array2)\n    result[0][0] // $ExpectType number\n    result[0][1] // $ExpectType string\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#zip)\n\n### zipWith\n\n```typescript\n\nzipWith\u003cT, U, TResult\u003e(\n  fn: (x: T, y: U) =\u003e TResult,\n  list1: readonly T[],\n): (list2: readonly U[]) =\u003e TResult[]\n```\n\n```javascript\nconst list1 = [ 10, 20, 30, 40 ]\nconst list2 = [ 100, 200 ]\n\nconst result = R.zipWith(R.add, list1)(list2)\n// =\u003e [110, 220]\n```\n\n\u003ca title=\"redirect to Rambda Repl site\" href=\"https://rambda.now.sh?const%20list1%20%3D%20%5B%2010%2C%2020%2C%2030%2C%2040%20%5D%0Aconst%20list2%20%3D%20%5B%20100%2C%20200%20%5D%0A%0Aconst%20result%20%3D%20R.zipWith(R.add%2C%20list1)(list2)%0A%2F%2F%20%3D%3E%20%5B110%2C%20220%5D\"\u003eTry this \u003cstrong\u003eR.zipWith\u003c/strong\u003e example in Rambda REPL\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAll TypeScript definitions\u003c/summary\u003e\n\n```typescript\nzipWith\u003cT, U, TResult\u003e(\n  fn: (x: T, y: U) =\u003e TResult,\n  list1: readonly T[],\n): (list2: readonly U[]) =\u003e TResult[];\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eR.zipWith\u003c/strong\u003e source\u003c/summary\u003e\n\n```javascript\nimport { take } from './take.js'\n\nexport function zipWith(fn, x) {\n  return y =\u003e\n    take(x.length \u003e y.length ? y.length : x.length)(x).map((xInstance, i) =\u003e\n      fn(xInstance, y[i]),\n    )\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTests\u003c/strong\u003e\u003c/summary\u003e\n\n```javascript\nimport { zipWith } from './zipWith.js'\n\nconst add = (x, y) =\u003e x + y\nconst list1 = [1, 2, 3]\nconst list2 = [10, 20, 30, 40]\nconst list3 = [100, 200]\n\ntest('when second list is shorter', () =\u003e {\n  const result = zipWith(add, list1)(list3)\n  expect(result).toEqual([101, 202])\n})\n\ntest('when second list is longer', () =\u003e {\n  const result = zipWith(add, list1)(list2)\n  expect(result).toEqual([11, 22, 33])\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u003cstrong\u003eTypeScript\u003c/strong\u003e test\u003c/summary\u003e\n\n```typescript\nimport { pipe, zipWith } from 'rambda'\n\nconst list1 = [1, 2]\nconst list2 = [10, 20, 30]\n\ndescribe('R.zipWith', () =\u003e {\n  it('happy', () =\u003e {\n    const result = pipe(\n      list2,\n      zipWith((x, y) =\u003e {\n        x // $ExpectType number\n        y // $ExpectType number\n        return `${x}-${y}`\n      }, list1),\n    )\n\n    result // $ExpectType string[]\n  })\n})\n```\n\n\u003c/details\u003e\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#zipWith)\n\n## ❯ CHANGELOG\n\n10.0.0\n\nCHANGELOG - 10.0.0\n\nThis is major revamp of `Rambda` library:\n\n- `R.pipe` is the recommended method for TypeScript chaining.\n\n- All methods should be useful to work inside `R.pipe` chain. If method doesn't have clear use case inside `R.pipe`, it is removed as part of this revamp.\n\n- There will be only one way to use each method. For example, `R.add` can be used only with `R.add(1)(2)`, i.e. it doesn't support `R.add(1, 2)`. This helps with testing and also with TypeScript definitions. This aligns with TypeScript focused approach of this library.\n\n- Confusing methods are removed. For example, `R.cond` and `R.ifElse` are removed as their usage inside `R.piped` makes the whole chain less readable. Such logic should be part of your codebase, not part of external library.\n\n- All methods that expect more than 1 input, will have to be called with `R.methodName(input1)(input2)` or `R.methodName(input1, input2)(input3)`. This is to make TypeScript definitions easier to maintain. \n\n- Optimize many methods to better work in TypeScript context with `R.pipe`. The focus was passing objects through the `R.pipe` chain.\n\n- Add `R.pipe` supports up to 20 functions, i.e. chain can be 20 functions long.\n\n- `R.chain` is renamed to `R.flatMap`\n- `R.comparator` is renamed to `R.sortingFn`\n\n- Remove following methods:\n\n-- Lenses - `R.lens`, `R.lensProp`, `R.lensPath`, `R.view`, `R.set`, `R.over`\n-- T, F\n-- add\n-- addIndex, addIndexRight\n-- always\n-- ap\n-- applySpec\n-- applyTo\n-- assoc, assocPath, dissoc, dissocPath\n-- binary\n-- bind\n-- call\n-- collectBy\n-- compose\n-- composeWith\n-- cond\n-- converge\n-- curry\n-- difference, differenceWith\n-- divide, multiply, subtract\n-- endsWith/startsWith\n-- flip\n-- forEachObjIndexed\n-- fromPairs\n-- gte, lte, lt, gt\n-- identical\n-- ifElse\n-- insert\n-- juxt\n-- length\n-- mapObjIndexed\n-- mergeAll, mergeLeft, mergeDeepLeft, mergeDeepRight\n-- move\n-- partitionIndexed\n-- pickAll\n-- pickBy\n-- repeat\n-- splitWhen\n-- toLower/toUpper\n-- unapply\n-- unnest\n-- update\n-- without\n\n- Add following methods:\n\n-- R.pipeAsync\n-- R.addProp\n-- R.createObjectFromKeys\n-- R.mapAsync\n-- R.mapParallelAsync\n-- R.ascend/R.descend\n-- R.shuffle\n-- R.permutations\n-- R.compact\n-- R.rejectObject\n-- R.findNth\n-- R.combinations\n-- R.rangeDescending\n\n- Rename following methods:\n\n-- replaceItemAtIndex -\u003e adjust\n-- checkObjectWithSpec -\u003e where \n-- objectIncludes -\u003e whereEq\n-- modify -\u003e modifyProp\n\n_ Regarding using object as input with TypeScript in methods such as `R.map/filter` - this feature is no longer supported in TypeScript as it has multiple issues when using inside pipes. In JS, it still works as before. Following methods are affected:\n\n-- R.map\n-- R.mapIndexed\n-- R.filter\n-- R.reject\n\n- Regarding using string as path input in `R.omit`, `R.pick` and `R.path` with TypeScript - now it require explicit definition of expected return type.\n\n- Revert adding stopper logic in `R.reduce` - https://github.com/selfrefactor/rambda/pull/630\n\n- Remove use of `Dictionary` custom interface and use more appropriate `Record\u003cPropertyType, ...\u003e`\n\n- Remove use of `Record\u003cstring, ...\u003e` in favour of `Record\u003cPropertyType, ...\u003e`\n\n- Add TypeScript definition to handle common case of `R.filter(Boolean)` that will turn `Array\u003cT | undefined\u003e` to `Array\u003cT\u003e`.\n\n- Regarding using object with `R.forEach` in TypeScript - this is no longer supported. Again, JS version still works with objects.\n\n- head/last - empty array as input will return `undefined`, but `never`\n- assocPath - stop supporting curring of type `(x)(y)(z)`\n\n- Stop support string inputs for some methods, since it was hard to correctly type them in TypeScript.\n\n-- append/prepend\n\n- Change `R.range` to work with `endIndex` included instead of `endIndex` excluded, i.e. `R.range(0, 2)` will return `[0, 1, 2]` instead of `[0, 1]`. This is done because `R.rangeDescending` is added and users would wonder if end or start index is excluded.\n\n- Sync with typing of `@types/ramda`:\n\n-- allPass\n-- anyPass\n-- append\n-- both\n-- countBy\n-- drop\n-- dropLast\n-- dropRepeatsBy\n-- either\n-- filter\n-- forEach\n-- keys\n-- map\n-- mergeAll\n-- modify\n-- modifyPath\n-- omit\n-- partition\n-- pluck\n-- prepend\n-- propEq\n-- where\n-- whereAny\n\n- Sync with typing of `remeda`:\n\n-- filter\n-- reject\n-- map\n-- mapObject\n-- toPairs\n-- partition\n\n- Publish to JSR registry - https://jsr.io/@rambda/rambda\n\n- Replace Record\u003cstring\u003e with Record\u003cPropertyKey\u003e\n\n- Improve TypeScript definitions of:\n\n-- objOf\n-- pluck\n-- mergeWith\n\n- Change `Jest` with `Vitest`.\n\n- Remove `Babel` dependency in `Rollup` build setup.\n\n- Revert adding stopper logic in `R.reduce` - https://github.com/selfrefactor/rambda/pull/630\n\n- Renamed methods: \n\n-- `chain` to `flatMap`\n-- `mapObjIndexed` to `mapObject`\n\n9.4.2\n\n- Fix TS issue when `R.take` is used as part of `R.pipe`.\n\nMoving away from `Ramda` types which are problematic in this case:\n\n```typescript\nconst data = ['foo', 'bar', 'baz', 'qux']\nconst result = piped(\n\tdata,\n\tfilter(\n\t\tx =\u003e x.length \u003e= 2\n\t),\n\ttakeLast(2),\n)\n```\n\n9.4.1\n\n- Fix bug with `R.differenceWith` when two arrays has same length - [Issue #750](https://github.com/selfrefactor/rambda/issues/757)\n\n- Allow path input to not be transformed when string numbers are there - [Issue #750](https://github.com/selfrefactor/rambda/issues/750)\n\n9.4.0\n\n- Fix `deno` release\n\n- Fix too strict `true` condition in `R.ifElse` - [Issue #750](https://github.com/selfrefactor/rambda/issues/750)\n\n- Change `R.groupBy` typings to match `@types/ramda` typings\n\n9.3.0\n\n- Breaking change in relation to TS typings of `R.assoc`, `R.dissoc` and `R.modify` - https://github.com/ramda/types/pull/37\n\n- Add `R.isNotEmpty` as it is new method in `Ramda`\n\n- Fix `R.head`/`R.last` TS definition - It returns `undefined` if array has length of 0. Before \n\n9.2.1\n\n- Broken `Deno` build - [Issue #731](https://github.com/selfrefactor/rambda/issues/731)\n\n9.2.0\n\n- `R.once` TS type definition miss to context argument and its type - [Issue #728](https://github.com/selfrefactor/rambda/issues/728)\n\n- Fix implementation of `R.unless` function - https://github.com/selfrefactor/rambda/pull/726 \n\n9.1.1\n\n- Faster R.equals with Object.is short circuit - https://github.com/selfrefactor/rambda/pull/725\n\n- Fix R.cond transform is unary - https://github.com/selfrefactor/rambda/issues/720\n\n9.1.0\n\nAdd these methods\n\n- insert\n- insertAll\n- lt\n- lte\n- isNotNil\n- pickBy\n- pathSatisfies\n- swap\n- mergeDeepLeft\n\n9.0.1\n\n- Fix bad TS typings, due to missing declaration - [Issue #716](https://github.com/selfrefactor/rambda/issues/716)\n\n9.0.0\n\nBreaking change in TS definitions of `lenses` as now they are synced to `Ramda` types.\n\n- Add `R.sortWith` - [Issue #707](https://github.com/selfrefactor/rambda/issues/707)\n\n- Add `R.innerJoin`, `R.gt`, `R.gte`, `R.reduceBy`, `R.hasIn`\n\n8.6.0\n\n- Wrong typing for `R.dissocPath` - [Issue #709](https://github.com/selfrefactor/rambda/issues/709)\n\n- Update build dependencies\n\n8.5.0\n\n- Revert changes in `R.anyPass` introduced in `8.4.0` release. The reason is that the change was breaking the library older than `5.2.0` TypeScript.\n\n- Wrong `R.partial` TS definition  - [Issue #705](https://github.com/selfrefactor/rambda/issues/705)\n\n- Add `R.dropRepeatsBy`\n\n- Add `R.empty`\n\n- Add `R.eqBy`\n\n- Add `R.forEachObjIndexed`\n\n8.4.0\n\n- Add `R.dissocPath`\n\n- Fix TS definitions of `R.head/R.last` and add missing handle of empty string\n\n- Add `R.removeIndex` - method was before only in `Rambdax`, but now since `R.dissocPath` is using it, it is added to main library.\n\n- Allow `R.omit` to pass numbers as part of properties to omit, i.e. `R.omit(['a', 1], {a: {1: 1, 2: 2}})`\n\n- R.keys always returns strings - [MR #700](https://github.com/selfrefactor/rambda/pull/700)\n\n- Improve `R.prepend/R.append` type interference - [MR #699](https://github.com/selfrefactor/rambda/pull/699)\n\n- Change `R.reduce` TS definitions so index is always received - [MR #696](https://github.com/selfrefactor/rambda/pull/696)\n\n- Functions as a type guard in `R.anyPass` TS definitions - [MR #695](https://github.com/selfrefactor/rambda/pull/695)\n\n- Fix R.append's curried type - [MR #694](https://github.com/selfrefactor/rambda/pull/694)\n\n- Fix cannot compare errors in `Deno` with `R.equals` - [Issue #704](https://github.com/selfrefactor/rambda/issues/704).\n\n- Fix cannot compare `BigInt` with `R.equals` \n\n8.3.0\n\nAdd the following methods:\n\n- binary\n- call\n- collectBy\n- comparator\n- composeWith\n\n8.2.0\n\nAdd the following methods:\n\n- addIndex\n- addIndexRight\n- ap\n- aperture\n- applyTo\n- ascend\n- descend\n\n8.1.0\n\n- Fix input order of TS definitions for `R.propEq` method  - [Issue #688](https://github.com/selfrefactor/rambda/issues/688). The issue was due to 8.0.0 was shipped with TS definitions of `7.5.0` release.\n\n- Add `R.differenceWith` method  - [Issue #91](https://github.com/selfrefactor/rambdax/issues/91)\n\n8.0.0\n\n- handle falsy values in merge methods - https://github.com/ramda/ramda/pull/3222\n\n- `R.head`/`R.last` don't return `undefined` for non-empty arrays\n\n- `R.type` supports dates in TS definition - `Rambda` already did support dates in JS.\n\n- Improve typings of `R.endsWith/startsWith` with regard to `string` input. - [PR #622](https://github.com/selfrefactor/rambda/pull/622)\n\n- Handle list as falsy value in `R.reduce` - [Ramda MR](https://github.com/ramda/ramda/pull/2997/files)\n\n- `R.nop` is removed - it will be moved to `Rambdax` as `R.noop`\n\n- `R.includes` is no longer using string literal in TypeScript definitions\n\n\u003e Reason for breaking change - synchronize with Ramda `0.29.0` release:\n\n- change order of `R.propEq` - [Ramda MR](https://github.com/ramda/ramda/pull/2938/files)\n\n7.5.0\n\n- IMPORTANT: Remove `export` property in `package.json` in order to allow `Rambda`  support for projects with `\"type\": \"module\"` in `package.json` - [Issue #667](https://github.com/selfrefactor/rambda/issues/657)\n\n- Add `R.unnest` - [Rambdax issue 89](https://github.com/selfrefactor/rambdax/issues/89)\n\n- `R.uniq` is not using `R.equals` as Ramda does - [Issue #88](https://github.com/selfrefactor/rambdax/issues/88)\n\n- Fix `R.path(['non','existing','path'], obj)` TS definition as 7.4.0 release caused TS errors - [Issue #668](https://github.com/selfrefactor/rambda/issues/668)\n\n7.4.0\n\n- Synchronize with `@types/ramda` - `R.prop`, `R.path`, `R.pickAll`\n\n- Remove `esm` Rollup output due to tree-shaking issues.\n\n- Upgrade all dev dependencies.\n\n7.3.0\n\n- Important - changing import declaration in `package.json` in order to fix tree-shaking issue - [Issue #647](https://github.com/selfrefactor/rambda/issues/647)\n\n- Add `R.modify`\n\n- Allow multiple inputs in TypeScript versions of `R.anyPass` and `R.allPass` - [Issue #642](https://github.com/selfrefactor/rambda/issues/604)\n\n- Using wrong clone of object in `R.mergeDeepRight` - [Issue #650](https://github.com/selfrefactor/rambda/issues/650)\n\n- Missing early return in `R.where` - [Issue #648](https://github.com/selfrefactor/rambda/issues/648)\n\n- `R.allPass` doesn't accept more than 1 parameters for function predicates- [Issue #604](https://github.com/selfrefactor/rambda/issues/604)\n\n7.2.1\n\n- Remove bad typings of `R.propIs` which caused the library to cannot be build with TypeScript. \n\n- Drop support for `Wallaby` as per [https://github.com/wallabyjs/public/issues/3037](https://github.com/wallabyjs/public/issues/3037)\n\n7.2.0\n\n- Wrong `R.update` if index is `-1` - [PR #593](https://github.com/selfrefactor/rambda/pull/593)\n\n- Wrong curried typings in `R.anyPass` - [Issue #642](https://github.com/selfrefactor/rambda/issues/642)\n\n- `R.modifyPath` not exported - [Issue #640](https://github.com/selfrefactor/rambda/issues/640)\n\n- Add new method `R.uniqBy`. Implementation is coming from [Ramda MR#2641](https://github.com/ramda/ramda/pull/2641)\n\n- Apply the following changes from `@types/rambda`:\n\n-- [https://github.com/DefinitelyTyped/DefinitelyTyped/commit/bab47272d52fc7bb81e85da36dbe9c905a04d067](add `AnyFunction` and `AnyConstructor`)\n\n-- Improve `R.ifElse` typings - https://github.com/DefinitelyTyped/DefinitelyTyped/pull/59291\n\n-- Make `R.propEq` safe for `null/undefined` arguments - https://github.com/ramda/ramda/pull/2594/files\n\n7.1.4\n\n- `R.mergeRight` not found on `Deno` import - [Issue #633](https://github.com/selfrefactor/rambda/issues/633)\n\n7.1.0\n\n- Add `R.mergeRight` - introduced by Ramda's latest release. While Ramda renames `R.merge`, Rambda will keep `R.merge`.\n\n- Rambda's `pipe/compose` doesn't return proper length of composed function which leads to issue with `R.applySpec`. It was fixed by using Ramda's `pipe/compose` logic - [Issue #627](https://github.com/selfrefactor/rambda/issues/627)\n\n- Replace `Async` with `Promise` as return type of `R.type`.\n\n- Add new types as TypeScript output for `R.type` - \"Map\", \"WeakMap\", \"Generator\", \"GeneratorFunction\", \"BigInt\", \"ArrayBuffer\"\n\n- Add `R.juxt` method\n\n- Add `R.propSatisfies` method\n\n- Add new methods after `Ramda` version upgrade to `0.28.0`:\n\n-- R.count\n-- R.modifyPath\n-- R.on\n-- R.whereAny\n-- R.partialObject\n\n7.0.3\n\nRambda.none has wrong logic introduced in version `7.0.0` - [Issue #625](https://github.com/selfrefactor/rambda/issues/625)\n\n7.0.2\n\nRambda doesn't work with `pnpm` due to wrong export configuration - [Issue #619](https://github.com/selfrefactor/rambda/issues/619)\n\n7.0.1\n\n- Wrong ESM export configuration in `package.json` - [Issue #614](https://github.com/selfrefactor/rambda/issues/614)\n\n7.0.0\n\n- Breaking change - sync `R.compose`/`R.pipe` with `@types/ramda`. That is significant change so as safeguard, it will lead a major bump. Important - this lead to raising required TypeScript version to `4.2.2`. In other words, to use `Rambda` you'll need TypeScript version `4.2.2` or newer.\n\nRelated commit in `@types/ramda` - https://github.com/DefinitelyTyped/DefinitelyTyped/commit/286eff4f76d41eb8f091e7437eabd8a60d97fc1f#diff-4f74803fa83a81e47cb17a7d8a4e46a7e451f4d9e5ce2f1bd7a70a72d91f4bc1\n\nThere are several other changes in `@types/ramda` as stated in [this comment](https://github.com/ramda/ramda/issues/2976#issuecomment-990408945). This leads to change of typings for the following methods in **Rambda**:\n\n-- R.unless\n\n-- R.toString\n\n-- R.ifElse\n\n-- R.always\n\n-- R.complement\n\n-- R.cond\n\n-- R.is\n\n-- R.sortBy\n\n-- R.dissoc\n\n-- R.toPairs\n\n-- R.assoc\n\n-- R.toLower\n\n-- R.toUpper\n\n- One more reason for the breaking change is changing of export declarations in `package.json` based on [this blog post](https://devblogs.microsoft.com/typescript/announcing-typescript-4-5-beta/#packagejson-exports-imports-and-self-referencing) and [this merged Ramda's PR](https://github.com/ramda/ramda/pull/2999). This also led to renaming of `babel.config.js` to `babel.config.cjs`. \n\n- Add `R.apply`, `R.bind` and `R.unapply`\n\n- `R.startsWith/R.endsWith` now support lists as inputs. This way, it matches current Ramda behavior. \n\n- Remove unused typing for `R.chain`.\n\n- `R.map`/`R.filter` no longer accept bad inputs as iterable. This way, Rambda behaves more like Ramda, which also throws.\n\n- Make `R.lastIndexOf` follow the logic of `R.indexOf`.\n\n- Change `R.type` logic to Ramda logic. This way, `R.type` can return `Error` and `Set` as results.\n\n- Add missing logic in `R.equals` to compare sets - [Issue #599](https://github.com/selfrefactor/rambda/issues/599)\n\n- Improve list cloning - [Issue #595](https://github.com/selfrefactor/rambda/issues/595)\n\n- Handle multiple inputs with `R.allPass` and `R.anyPass` - [Issue #604](https://github.com/selfrefactor/rambda/issues/604)\n\n- Fix `R.length` wrong logic with inputs as `{length: 123}` - [Issue #606](https://github.com/selfrefactor/rambda/issues/606).\n\n- Improve non-curry typings of `R.merge` by using types from [mobily/ts-belt](https://github.com/mobily/ts-belt).\n\n- Improve performance of `R.uniqWith`.\n\n- Wrong `R.update` if index is `-1` - [PR #593](https://github.com/selfrefactor/rambda/pull/593)\n\n- Make `R.eqProps` safe for falsy inputs - based on [this opened Ramda PR](https://github.com/ramda/ramda/pull/2943).\n\n- Incorrect benchmarks for `R.pipe/R.compose` - [Issue #608](https://github.com/selfrefactor/rambda/issues/608)\n\n- Fix `R.last/R.head` typings - [Issue #609](https://github.com/selfrefactor/rambda/issues/609) \n\n6.9.0\n\n- Fix slow `R.uniq` methods - [Issue #581](https://github.com/selfrefactor/rambda/issues/581)\n\nFixing `R.uniq` was done by improving `R.indexOf` which has performance implication to all methods importing `R.indexOf`:\n\n- R.includes\n- R.intersection\n- R.difference\n- R.excludes\n- R.symmetricDifference\n- R.union\n\n- R.without no longer support the following case - `without('0:1', ['0', '0:1']) // =\u003e ['0']`. Now it throws as the first argument should be a list, not a string. Ramda, on the other hand, returns an empty list - https://github.com/ramda/ramda/issues/3086. \n\n6.8.3\n\n- Fix TypeScript build process with `rambda/immutable` - [Issue #572](https://github.com/selfrefactor/rambda/issues/572)\n\n- Add `R.objOf` method\n\n- Add `R.mapObjIndexed` method\n\n- Publish shorter README.md version to NPM\n\n6.8.0\n\n- `R.has` use `Object.prototype.hasOwnProperty`- [Issue #572](https://github.com/selfrefactor/rambda/issues/572)\n\n- Expose `immutable.ts` typings which are Rambda typings with `readonly` statements - [Issue #565](https://github.com/selfrefactor/rambda/issues/565)\n\n- Fix `R.intersection` wrong order compared to Ramda.\n\n- `R.path` wrong return of `null` instead of `undefined` when path value is `null` - [PR #577](https://github.com/selfrefactor/rambda/pull/577)\n\n6.7.0\n\n- Remove `ts-toolbelt` types from TypeScript definitions. Most affected are the following methods, which lose one of its curried definitions:\n\n1. R.maxBy\n2. R.minBy\n3. R.pathEq\n4. R.viewOr\n5. R.when\n6. R.merge\n7. R.mergeDeepRight\n8. R.mergeLeft\n\n6.6.0\n\n- Change `R.piped` typings to mimic that of `R.pipe`. Main difference is that `R.pipe` is focused on unary functions.\n\n- Fix wrong logic when `R.without` use `R.includes` while it should use array version of `R.includes`.\n\n- Use uglify plugin for UMD bundle.\n\n- Remove `dist` folder from `.gitignore` in order to fix `Deno` broken package. [Issue #570](https://github.com/selfrefactor/rambda/issues/570)\n\n- Improve `R.fromPairs` typings - [Issue #567](https://github.com/selfrefactor/rambda/issues/567)\n\n6.5.3\n\n- Wrong logic where `R.without` use `R.includes` while it should use the array version of `R.includes`\n\nThis is Ramda bug, that Rambda also has before this release - https://github.com/ramda/ramda/issues/3086\n\n6.5.2\n\n- Wrong `R.defaultTo` typings - changes introduced in v6.5.0 are missing their TS equivalent.\n\n- Update dependencies\n\n6.5.1\n\nFix wrong versions in changelog\n\n6.5.0\n\n- `R.defaultTo` no longer accepts infinite inputs, thus it follows Ramda implementation.\n\n- `R.equals` supports equality of functions.\n\n- `R.pipe` doesn't use `R.compose`.\n\n- Close [Issue #561](https://github.com/selfrefactor/rambda/issues/561) - export several internal TS interfaces and types\n\n- Close [Issue #559](https://github.com/selfrefactor/rambda/issues/559) - improve `R.propOr` typings\n\n- Add `CHANGELOG.md` file in release files list\n\n\u003e This is only part of the changelog. You can read the full text in [CHANGELOG.md](CHANGELOG.md) file.\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#-changelog)\n\n## ❯ Additional info\n\n\u003e Most influential contributors(in alphabetical order)\n\n- ![farwayer avatar](https://avatars.githubusercontent.com/farwayer) [@farwayer](https://github.com/farwayer) - improving performance in R.find, R.filter; give the idea how to make benchmarks more reliable;\n\n- ![thejohnfreeman avatar](https://avatars.githubusercontent.com/thejohnfreeman) [@thejohnfreeman](https://github.com/thejohnfreeman) - add R.assoc, R.chain;\n\n- ![peeja avatar](https://avatars.githubusercontent.com/peeja) [@peeja](https://github.com/peeja) - add several methods and fix mutiple issues; provides great MR documentation\n\n- ![helmuthdu avatar](https://avatars.githubusercontent.com/helmuthdu) [@helmuthdu](https://github.com/helmuthdu) - add R.clone; help improve code style;\n\n- ![jpgorman avatar](https://avatars.githubusercontent.com/jpgorman) [@jpgorman](https://github.com/jpgorman) - add R.zip, R.reject, R.without, R.addIndex;\n\n- ![ku8ar avatar](https://avatars.githubusercontent.com/ku8ar) [@ku8ar](https://github.com/ku8ar) - add R.slice, R.propOr, R.identical, R.propIs and several math related methods; introduce the idea to display missing Ramda methods;\n\n- ![romgrk avatar](https://avatars.githubusercontent.com/romgrk) [@romgrk](https://github.com/romgrk) - add R.groupBy, R.indexBy, R.findLast, R.findLastIndex;\n\n- ![squidfunk avatar](https://avatars.githubusercontent.com/squidfunk) [@squidfunk](https://github.com/squidfunk) - add R.assocPath, R.symmetricDifference, R.difference, R.intersperse;\n\n- ![synthet1c avatar](https://avatars.githubusercontent.com/synthet1c) [@synthet1c](https://github.com/synthet1c) - add all lenses methods; add R.applySpec, R.converge;\n\n- ![vlad-zhukov avatar](https://avatars.githubusercontent.com/vlad-zhukov) [@vlad-zhukov](https://github.com/vlad-zhukov) - help with configuring Rollup, Babel; change export file to use ES module exports;\n\n\u003e Rambda references\n\n- [Interview with Dejan Totef at SurviveJS blog](https://survivejs.com/blog/rambda-interview/)\n\n- [Awesome functional Javascript programming libraries](https://github.com/stoeffel/awesome-fp-js#libraries)\n\n- [Overview of Rambda pros/cons](https://mobily.github.io/ts-belt/docs/#rambda-%EF%B8%8F)\n\n\u003e Links to Rambda\n\n- [awesome-fp-js](https://github.com/stoeffel/awesome-fp-js)\n\n- [Web Tools Weekly #280](https://mailchi.mp/webtoolsweekly/web-tools-280)\n\n- [awesome-docsify](https://github.com/docsifyjs/awesome-docsify)\n\n\u003e Deprecated from `Used by` section\n\n- [SAP's Cloud SDK](https://github.com/SAP/cloud-sdk) - This repo doesn't uses `Rambda` since *October/2020* [commit that removes Rambda](https://github.com/SAP/cloud-sdk/commit/b29b4f915c4e4e9c2441e7b6b67cf83dac1fdac3)\n\n[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#-additional-info)\n\n## My other libraries\n\n\u003ctable\u003e\n    \u003ctbody\u003e\n        \u003ctr valign=\"top\"\u003e\n            \u003ctd width=\"20%\" align=\"center\"\u003e\n                \u003ch4\u003eNiketa theme\u003c/h4\u003e\n                \u003ca href=\"https://marketplace.visualstudio.com/items?itemName=selfrefactor.Niketa-theme\"\u003eCollection of 9 light VSCode themes\u003c/a\u003e\n            \u003c/td\u003e\n            \u003ctd width=\"20%\" align=\"center\"\u003e\n                \u003ch4\u003eNiketa dark theme\u003c/h4\u003e\n                \u003ca href=\"https://marketplace.visualstudio.com/items?itemName=selfrefactor.niketa-dark-theme\"\u003eCollection of 9 dark VSCode themes\u003c/a\u003e\n            \u003c/td\u003e\n            \u003ctd width=\"20%\" align=\"center\"\u003e\n                \u003ch4\u003eString-fn\u003c/h4\u003e\n                \u003ca href=\"https://github.com/selfrefactor/services/tree/master/packages/string-fn\"\u003eString utility library\u003c/a\u003e\n            \u003c/td\u003e\n            \u003ctd width=\"20%\" align=\"center\"\u003e\n                \u003ch4\u003eUseful Javascript libraries\u003c/h4\u003e\n                \u003ca href=\"https://github.com/selfrefactor/useful-javascript-libraries\"\u003eLarge collection of JavaScript,TypeScript and Angular related repos links\u003c/a\u003e\n            \u003c/td\u003e\n            \u003ctd width=\"20%\" align=\"center\"\u003e\n                \u003ch4\u003eRun-fn\u003c/h4\u003e\n                \u003ca href=\"https://github.com/selfrefactor/services/tree/master/packages/run-fn\"\u003eCLI commands for lint JS/TS files, commit git changes and upgrade of dependencies\u003c/a\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n    \u003c/tbody\u003e\n\u003c/table\u003e\n\n## Stargazers over time\n\n[![Stargazers over time](https://starchart.cc/selfrefactor/rambda.svg)](https://starchart.cc/selfrefactor/rambda)","funding_links":[],"categories":["JavaScript","Uncategorized","Functional Programming","functional-programming","Functional Programming [🔝](#readme)","函数式编程","Libraries","Generic Utilities"],"sub_categories":["Uncategorized","Runner","运行器","运行器e2e测试","Reactive Programming"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fselfrefactor%2Frambda","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fselfrefactor%2Frambda","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fselfrefactor%2Frambda/lists"}