{"id":13998360,"url":"https://github.com/rametta/pratica","last_synced_at":"2025-05-16T03:03:44.050Z","repository":{"id":34179401,"uuid":"170429491","full_name":"rametta/pratica","owner":"rametta","description":"🥃 Functional Algebraic Data Types","archived":false,"fork":false,"pushed_at":"2024-06-05T15:45:57.000Z","size":173,"stargazers_count":479,"open_issues_count":0,"forks_count":19,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-05-12T11:50:59.323Z","etag":null,"topics":["fp","functional-programming","monads","monoids","typescript","utilities"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rametta.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-02-13T02:55:02.000Z","updated_at":"2025-04-27T16:39:23.000Z","dependencies_parsed_at":"2024-01-02T23:42:40.012Z","dependency_job_id":"1a75959d-c4ee-4eba-9048-914fcca63f2e","html_url":"https://github.com/rametta/pratica","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rametta%2Fpratica","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rametta%2Fpratica/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rametta%2Fpratica/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rametta%2Fpratica/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rametta","download_url":"https://codeload.github.com/rametta/pratica/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254459082,"owners_count":22074604,"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-programming","monads","monoids","typescript","utilities"],"created_at":"2024-08-09T19:01:36.699Z","updated_at":"2025-05-16T03:03:39.041Z","avatar_url":"https://github.com/rametta.png","language":"TypeScript","readme":"[![npm](https://img.shields.io/npm/v/pratica.svg)](http://npm.im/pratica)\n[![Pratica](https://badgen.net/bundlephobia/minzip/pratica)](https://bundlephobia.com/result?p=pratica)\n[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\n[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-blue.svg)](http://makeapullrequest.com)\n\n# 🥃 Pratica\n\n\u003e Functional Programming for Pragmatists\n\n_Why is this for pragmatists you say?_\n\nPratica sacrifices some common FP guidelines in order to provide a simpler and more approachable API that can be used to accomplish your goals quickly - while maintaining data integrity and safety, through algrebraic data types.\n\n## Install\n\n```sh\nbun i pratica\n# or\nyarn add pratica\n# or\nnpm i pratica\n```\n\n## Documentation\n\n### Monads\n\n#### Maybe\n\nUse this when dealing with nullable and unreliable data that needs actions performed upon.\n\nMaybe is great for making sure you do not cause runtime errors by accessing data that is not there because of unexpected nulls or undefineds.\n\nEvery Maybe can either be of type `Just` or `Nothing`. When the data is available, it is wrapped with `Just`, if the data is missing, it is `Nothing`. The examples below should clarify futher.\n\n##### Maybe.map\n\nMap is used for running a function on the data inside the Maybe. Map will only run the function if the Maybe type is `Just`. If it's Nothing, the map will [short circuit](https://en.wikipedia.org/wiki/Short-circuit_evaluation) and be skipped.\n\n```js\nimport { nullable } from \"pratica\"\n\nconst person = { name: \"Jason\", age: 4 }\n\n// Example with real data\nnullable(person)\n  .map((p) =\u003e p.age)\n  .map((age) =\u003e age + 5)\n  .cata({\n    Just: (age) =\u003e console.log(age), // 9\n    Nothing: () =\u003e console.log(`This function won't run`),\n  })\n\n// Example with null data\nnullable(null)\n  .map((p) =\u003e p.age) // Maybe type is Nothing, so this function is skipped\n  .map((age) =\u003e age + 5) // Maybe type is Nothing, so this function is skipped\n  .cata({\n    Just: (age) =\u003e console.log(age), // Maybe type is Nothing, so this function is not run\n    Nothing: () =\u003e console.log(\"Could not get age from person\"), // This function runs because Maybe is Nothing\n  })\n```\n\n##### Maybe.chain\n\nChain is used when you want to return another Maybe when already inside a Maybe.\n\n```js\nimport { nullable } from \"pratica\"\n\nconst person = { name: \"Jason\", age: 4 }\n\nnullable(person)\n  .chain((p) =\u003e nullable(p.height)) // p.height does not exist so nullable returns a Nothing type, any .map, .chain, or .ap after a Nothing will be short circuited\n  .map((height) =\u003e height * 2.2) // this func won't even run because height is Nothing, so `undefined * 2.2` will never execute, preventing problems.\n  .cata({\n    Just: (height) =\u003e console.log(height), // this function won't run because the height is Nothing\n    Nothing: () =\u003e console.log(\"This person has no height\"),\n  })\n```\n\n##### Maybe.alt\n\nAlt is a clean way of making sure you always return a Just with some _default_ data inside.\n\n```js\nimport { nullable } from \"pratica\"\n\n// Example with default data\nnullable(null)\n  .map((p) =\u003e p.age) // won't run\n  .map((age) =\u003e age + 5) // won't run\n  .alt(99) // the data is null so 99 is the default\n  .cata({\n    Just: (age) =\u003e console.log(age), // 99\n    Nothing: () =\u003e console.log(`This function won't run because .alt() always returns a Just`),\n  })\n```\n\n##### Maybe.ap\n\nSometime's working with Maybe can be reptitive to always call `.map` whenever needing to a apply a function to the contents of the Maybe. Here is an example using `.ap` to simplify this.\n\nGoal of this example, to perform operations on data inside the Maybe, without unwrapping the data with `.map` or `.chain`\n\n```js\nimport { Just, nullable } from \"pratica\"\n\n// Need something like this\n// Just(6) + Just(7) = Just(13)\nJust((x) =\u003e (y) =\u003e x + y)\n  .ap(Just(6))\n  .ap(Just(7))\n  .cata({\n    Just: (result) =\u003e console.log(result), // 13\n    Nothing: () =\u003e console.log(`This function won't run`),\n  })\n\nnullable(null) // no function to apply\n  .ap(Just(6))\n  .ap(Just(7))\n  .cata({\n    Just: () =\u003e console.log(`This function won't run`),\n    Nothing: () =\u003e console.log(`This function runs`),\n  })\n```\n\n##### Maybe.inspect\n\nInspect is used for seeing a string respresentation of the Maybe. It is used mostly for Node logging which will automatically call inspect() on objects that have it, but you can use it too for debugging if you like.\n\n```js\nimport { nullable } from \"pratica\"\n\nnullable(86).inspect() // `Just(86)`\nnullable(\"HELLO\").inspect() // `Just('HELLO')`\nnullable(null).inspect() // `Nothing`\nnullable(undefined).inspect() // `Nothing`\n```\n\n##### Maybe.cata\n\nCata is used at the end of your chain of computations. It is used for getting the final data from the Maybe. You must pass an object to `.cata` with 2 properties, `Just` and `Nothing` _(capitalization matters)_, and both those properties must be a function. Those functions will run based on if the the computations above it return a Just or Nothing data type.\n\nCata stands for catamorphism and in simple terms means that it extracts a value from inside any container.\n\n```js\nimport { Just, Nothing } from \"pratica\"\n\nconst isOver6Feet = (person) =\u003e (person.height \u003e 6 ? Just(person.height) : Nothing)\n\nisOver6Feet({ height: 4.5 })\n  .map((h) =\u003e h / 2.2)\n  .cata({\n    Just: (h) =\u003e console.log(h), // this function doesn't run\n    Nothing: () =\u003e console.log(`person is not over 6 feet`),\n  })\n```\n\n##### Maybe.toResult\n\ntoResult is used for easily converting Maybe's to Result's. Any Maybe that is a Just will be converted to an Ok with the same value inside, and any value that was Nothing will be converted to an Err with no value passed. The cata will have to include `Ok` and `Err` instead of `Just` and `Nothing`.\n\n```js\nimport { Just, Nothing } from \"pratica\"\n\nJust(8)\n  .toResult()\n  .cata({\n    Ok: (n) =\u003e console.log(n), // 8\n    Err: () =\u003e console.log(`No value`), // this function doesn't run\n  })\n\nNothing.toResult().cata({\n  Ok: (n) =\u003e console.log(n), // this function doesn't run\n  Err: () =\u003e console.log(`No value`), // this runs\n})\n```\n\n##### Maybe.isJust\n\nisJust returns a boolean representing the type of the Maybe. If the Maybe is a Just type then true is returned, if it's a Nothing, returns false.\n\n```js\nimport { Just, Nothing } from \"pratica\"\n\nconst isOver6Feet = (height) =\u003e (height \u003e 6 ? Just(height) : Nothing)\n\nisOver6Feet(7).isJust() // true\nisOver6Feet(4).isJust() // false\n```\n\n##### Maybe.isNothing\n\nisNothing returns a boolean representing the type of the Maybe. If the Maybe is a Just type then false is returned, if it's a Nothing, returns true.\n\n```js\nimport { Just, Nothing } from \"pratica\"\n\nconst isOver6Feet = (height) =\u003e (height \u003e 6 ? Just(height) : Nothing)\n\nisOver6Feet(7).isNothing() // false\nisOver6Feet(4).isNothing() // true\n```\n\n##### Maybe.value\n\nvalue returns the encapsulated value within the Maybe. If the Maybe is a Just type, then the `arg` is returned, otherwise, if it is a Nothing, then it returns undefined.\n\n```js\nimport { Just, Nothing } from \"pratica\"\n\nconst isOver6Feet = (height) =\u003e (height \u003e 6 ? Just(height) : Nothing)\n\nisOver6Feet(7).value() // 7\nisOver6Feet(4).value() // undefined\n```\n\n#### Result\n\nUse this when dealing with conditional logic. Often a replacment for if statements - or for simplifying complex logic trees. A Result can either be an `Ok` or an `Err` type.\n\n##### Result.map\n\n```js\nimport { Ok, Err } from \"pratica\"\n\nconst person = { name: \"jason\", age: 4 }\n\nOk(person)\n  .map((p) =\u003e p.name)\n  .cata({\n    Ok: (name) =\u003e console.log(name), // 'jason'\n    Err: (msg) =\u003e console.error(msg), // this func does not run\n  })\n```\n\n##### Result.chain\n\n```js\nimport { Ok, Err } from \"pratica\"\n\nconst person = { name: \"Jason\", age: 4 }\n\nconst isPerson = (p) =\u003e (p.name \u0026\u0026 p.age ? Ok(p) : Err(\"Not a person\"))\n\nconst isOlderThan2 = (p) =\u003e (p.age \u003e 2 ? Ok(p) : Err(\"Not older than 2\"))\n\nconst isJason = (p) =\u003e (p.name === \"jason\" ? Ok(p) : Err(\"Not jason\"))\n\nOk(person)\n  .chain(isPerson)\n  .chain(isOlderThan2)\n  .chain(isJason)\n  .cata({\n    Ok: (p) =\u003e console.log(\"this person satisfies all the checks\"),\n    Err: (msg) =\u003e console.log(msg), // if any checks return an Err, then this function will be called. If isPerson returns Err, then isOlderThan2 and isJason functions won't even execute, and the err msg would be 'Not a person'\n  })\n```\n\n##### Result.mapErr\n\nYou can also modify errors that may return from any result before getting the final result, by using `.mapErr` or `.chainErr`.\n\n```js\nimport { Err } from \"pratica\"\n\nErr(\"Message:\")\n  .mapErr((x) =\u003e x + \" Syntax Error\")\n  .map((x) =\u003e x + 7) // ignored because it's an error\n  .cata({\n    Ok: (x) =\u003e console.log(x), // function not ran\n    Err: (x) =\u003e console.log(x), // 'Message: Syntax Error'\n  })\n```\n\n##### Result.chainErr\n\n```js\nimport { Err } from \"pratica\"\n\nErr(\"Message:\")\n  .chainErr((x) =\u003e x + Err(\" Syntax Error\"))\n  .map((x) =\u003e x + 7) // ignored because it's an error\n  .cata({\n    Ok: (x) =\u003e console.log(x), // function not ran\n    Err: (x) =\u003e console.log(x), // 'Message: Syntax Error'\n  })\n```\n\n##### Result.swap\n\nUse `.swap()` to convert an Err to an Ok, or an Ok to an Err.\n\n```js\nimport { Ok } from \"pratica\"\n\nOk(\"hello\")\n  .swap()\n  .cata({\n    Ok: () =\u003e console.log(`doesn't run`),\n    Err: (x) =\u003e expect(x).toBe(\"hello\"), // true\n  })\n```\n\n##### Result.bimap\n\nUse `.bimap()` for easily modifying an Ok or an Err. Shorthand for providing both `.map` and `.mapErr`\n\n```js\nimport { Ok } from \"pratica\"\n\nOk(\"hello\")\n  .bimap(\n    (x) =\u003e x + \" world\",\n    (x) =\u003e x + \" goodbye\",\n  )\n  .cata({\n    Ok: (x) =\u003e expect(x).toBe(\"hello world\"), // true\n    Err: () =\u003e {},\n  })\n\nErr(\"hello\")\n  .bimap(\n    (x) =\u003e x + \" world\",\n    (x) =\u003e x + \" goodbye\",\n  )\n  .cata({\n    Ok: () =\u003e {},\n    Err: (x) =\u003e expect(x).toBe(\"hello goodbye\"), // true\n  })\n```\n\n##### Result.ap\n\n```js\nimport { Ok } from \"pratica\"\n\n// Need something like this\n// Ok(6) + Ok(7) = Ok(13)\nOk((x) =\u003e (y) =\u003e x + y)\n  .ap(Ok(6))\n  .ap(Ok(7))\n  .cata({\n    Ok: (result) =\u003e console.log(result), // 13\n    Err: () =\u003e console.log(`This function won't run`),\n  })\n\nOk(null) // no function to apply\n  .ap(Ok(6))\n  .ap(Ok(7))\n  .cata({\n    Ok: () =\u003e console.log(`This function won't run`),\n    Err: () =\u003e console.log(`This function runs`),\n  })\n```\n\n##### Result.inspect\n\n```js\nimport { Ok, Err } from \"pratica\"\n\nOk(86).inspect() // `Ok(86)`\nOk(\"HELLO\").inspect() // `Ok('HELLO')`\nErr(\"Something happened\").inspect() // `Err('Something happened')`\nErr(404).inspect() // `Err(404)`\n```\n\n##### Result.cata\n\n```js\nimport { Ok, Err } from \"pratica\"\n\nconst isOver6Feet = (person) =\u003e (person.height \u003e 6 ? Ok(person.height) : Err(\"person is not over 6 feet\"))\n\nisOver6Feet({ height: 4.5 })\n  .map((h) =\u003e h / 2.2)\n  .cata({\n    Ok: (h) =\u003e console.log(h), // this function doesn't run\n    Err: (msg) =\u003e console.log(msg), // `person is not over 6 feet`\n  })\n```\n\n##### Result.toMaybe\n\ntoMaybe is used for easily converting Result's to Maybe's. Any Result that is an Ok will be converted to a Just with the same value inside, and any value that was Err will be converted to a Nothing with no value passed. The cata will have to include `Just` and `Nothing` instead of `Ok` and `Err`.\n\n```js\nimport { Ok, Err } from \"pratica\"\n\nOk(8)\n  .toMaybe()\n  .cata({\n    Just: (n) =\u003e console.log(n), // 8\n    Nothing: () =\u003e console.log(`No value`), // this function doesn't run\n  })\n\nErr(8)\n  .toMaybe()\n  .cata({\n    Just: (n) =\u003e console.log(n), // this function doesn't run\n    Nothing: () =\u003e console.log(`No value`), // this runs\n  })\n```\n\n##### Result.isOk\n\n```js\nimport { Ok, Err } from \"pratica\"\n\nconst isOver6Feet = (height) =\u003e (height \u003e 6 ? Ok(height) : Err(\"Shorty\"))\n\nisOver6Feet(7).isOk() // true\nisOver6Feet(4).isOk() // false\n```\n\n##### Result.isErr\n\n```js\nimport { Ok, Err } from \"pratica\"\n\nconst isOver6Feet = (height) =\u003e (height \u003e 6 ? Ok(height) : Err(\"Shorty\"))\n\nisOver6Feet(7).isErr() // false\nisOver6Feet(4).isErr() // true\n```\n\n##### Result.value\n\nReturns either the value contained in the Ok, or the error in the Err\n\n```js\nimport { Ok, Err } from \"pratica\"\n\nconst six = Ok(6).value()\nconst error = Err(\"Something happened\").value()\n\nconsole.log(six) // 6\nconsole.log(error) // 'Something happened'\n```\n\n### Utilities\n\n#### parseDate\n\nSafely parse date strings. parseDate returns a Maybe monad.\n\n```js\nimport { parseDate } from \"pratica\"\n\nconst goodDate = \"2019-02-13T21:04:10.984Z\"\nconst badDate = \"2019-02-13T21:04:1\"\n\nparseDate(goodDate).cata({\n  Just: (date) =\u003e expect(date.toISOString()).toBe(goodDate),\n  Nothing: () =\u003e console.log(\"could not parse date string\"), // this function doesn't run\n})\n\nparseDate(badDate).cata({\n  Just: () =\u003e console.log(`this function doesn't run`),\n  Nothing: () =\u003e \"this function runs\",\n})\n\n// it's a maybe, so you can use chain/default/ap\nparseDate(null)\n  .default(() =\u003e new Date())\n  .cata({\n    Just: (date) =\u003e date.toISOString(), // this runs\n    Nothing: () =\u003e `doesn't run because of the .default()`,\n  })\n```\n\n#### encase\n\nSafely run functions that may throw an error or crash. encase returns a Maybe type (so Just or Nothing).\n\n```js\nimport { encase } from \"pratica\"\n\nconst throwableFunc = () =\u003e JSON.parse(\"\u003c\u003e\")\n\n// this func doesn't throw, so Just is called\nencase(() =\u003e \"hello\").cata({\n  Just: (x) =\u003e console.log(x), // hello\n  Nothing: () =\u003e console.log(\"func threw error\"), // this func doesn't run\n})\n\n// this function throws an error so Nothing is called\nencase(throwableFunc).cata({\n  Just: (json) =\u003e console.log(`doesn't run`),\n  Nothing: () =\u003e console.error(\"func threw an error\"), // this runs\n})\n```\n\n#### encaseRes\n\nSafely run functions that may throw an error or crash. encaseRes returns a Result type (so Ok or Err). Similar to `encase` but the Err returns the error message.\n\n```js\nimport { encaseRes } from \"pratica\"\n\nconst throwableFunc = () =\u003e JSON.parse(\"\u003c\u003e\")\n\n// this func doesn't throw, so Ok is called\nencaseRes(() =\u003e \"hello\").cata({\n  Ok: (x) =\u003e console.log(x), // hello\n  Err: () =\u003e console.log(\"func threw error\"), // this func doesn't run\n})\n\n// this function throws an error so Err is called\nencaseRes(throwableFunc).cata({\n  Ok: (json) =\u003e console.log(`doesn't run`),\n  Err: (msg) =\u003e console.error(msg), // SyntaxError: Unexpected token \u003c in JSON at position 0\n})\n```\n\n#### justs\n\nFilter out any non-Just data type from an array\n\n```js\nimport { justs } from \"pratica\"\n\nconst data = [1, true, Just(\"hello\"), Nothing, Ok(\"hey\"), Err(\"No good\")]\n\njusts(data) // returns [Just('hello')]\n```\n\n#### oks\n\nFilter out any non-Ok data type from an array\n\n```js\nimport { oks } from \"pratica\"\n\nconst data = [1, true, Just(\"hello\"), Nothing, Ok(\"hey\"), Err(\"No good\")]\n\noks(data) // returns [Ok('hey')]\n```\n\n#### get\n\nSafely retrieve a nested property in an object. Returns a Maybe.\n\n```js\nimport { get } from \"pratica\"\n\nconst data = {\n  name: \"jason\",\n  children: [\n    {\n      name: \"bob\",\n    },\n    {\n      name: \"blanche\",\n      children: [\n        {\n          name: \"lera\",\n        },\n      ],\n    },\n  ],\n}\n\nget([\"children\", 1, \"children\", 0, \"name\"])(data).cata({\n  Just: (name) =\u003e expect(name).toBe(\"lera\"), // true\n  Nothing: () =\u003e console.log(\"no name\"), // doesn't run\n})\n```\n\n#### head\n\nSafely get the first item in an array. Returns a Maybe.\n\n```js\nimport { head } from \"pratica\"\n\nconst data = [5, 1, 2]\n\n// example with data\nhead(data).cata({\n  Just: (x) =\u003e expect(x).toBe(5), // true,\n  Nothing: () =\u003e console.log(\"No head\"), // won't run\n})\n\n// example with empty data\nhead([]).cata({\n  Just: (x) =\u003e console.log(x), // doesn't run\n  Nothing: () =\u003e console.log(\"No head\"), // runs\n})\n```\n\n#### last\n\nSafely get the last item in an array. Returns a Maybe.\n\n```js\nimport { last } from \"pratica\"\n\nconst data = [5, 1, 2]\n\n// example with data\nlast(data).cata({\n  Just: (x) =\u003e expect(x).toBe(2), // true,\n  Nothing: () =\u003e console.log(\"No last\"), // won't run\n})\n\n// example with empty data\nlast([]).cata({\n  Just: (x) =\u003e console.log(x), // doesn't run\n  Nothing: () =\u003e console.log(\"No last\"), // runs\n})\n```\n\n#### tail\n\nSafely get the tail of an array (Everything except the first element). Returns a Maybe.\n\n```js\nimport { tail } from \"pratica\"\n\nconst data = [5, 1, 2]\n\n// example with data\ntail(data).cata({\n  Just: (x) =\u003e expect(x).toEqual([1, 2]), // true,\n  Nothing: () =\u003e console.log(\"No tail\"), // won't run\n})\n\n// example with empty data\nlast([]).cata({\n  Just: (x) =\u003e console.log(x), // doesn't run\n  Nothing: () =\u003e console.log(\"No tail\"), // runs\n})\n```\n\n#### tryFind\n\nSafely try to retrieve an item from an array. Returns a Maybe.\n\n```js\nimport { tryFind } from \"pratica\"\n\nconst users = [\n  { name: \"jason\", age: 6, id: \"123abc\" },\n  { name: \"bob\", age: 68, id: \"456def\" },\n]\n\ntryFind((u) =\u003e u.id === \"123abc\")(users).cata({\n  Just: (user) =\u003e expect(user).toEqual(users[0]), // true\n  Nothing: () =\u003e \"Could not find user with id 123abc\", // doesn't run\n})\n```\n\n#### collectResult\n\nSafely collect values from an array of results. Returns a result.\n\n```js\nimport { collectResult } from \"pratica\"\n\nconst all_good = [Ok(1), Ok(2), Ok(3)]\nconst one_bad = [Ok(1), Err(\"Some error\"), Ok(3)]\n\ncollectResult(all_good).cata({\n  Ok: (x) =\u003e expect(x).toEqual([1, 2, 3]), // true\n  Err: () =\u003e \"no values\", // doesn't run\n})\n\ncollectResult(one_bad).cata({\n  Ok: (x) =\u003e x, // doesn't run\n  Err: (err) =\u003e expect(err).toEqual(\"Some error\"), // true\n})\n```\n\n#### collectMaybe\n\nSafely collect values from an array of maybes. Returns a maybe.\n\n```js\nimport { collectMaybe } from \"pratica\"\n\nconst all_good = [Just(1), Just(2), Just(3)]\nconst one_bad = [Just(1), Nothing, Just(3)]\n\ncollectMaybe(all_good).cata({\n  Just: (x) =\u003e expect(x).toEqual([1, 2, 3]), // true\n  Nothing: () =\u003e \"no values\", // doesn't run\n})\n\ncollectMaybe(one_bad).cata({\n  Just: (x) =\u003e x, // doesn't run\n  Nothing: () =\u003e \"no values\", // true\n})\n```\n","funding_links":[],"categories":["TypeScript","Libraries"],"sub_categories":["Algebraic Data Types"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frametta%2Fpratica","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frametta%2Fpratica","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frametta%2Fpratica/lists"}