{"id":13625813,"url":"https://github.com/badrap/result","last_synced_at":"2025-04-12T21:33:47.432Z","repository":{"id":40482909,"uuid":"153687825","full_name":"badrap/result","owner":"badrap","description":"A TypeScript result type taking cues from Rust's Result and Haskell's Either types","archived":false,"fork":false,"pushed_at":"2024-05-02T14:26:12.000Z","size":766,"stargazers_count":295,"open_issues_count":5,"forks_count":6,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-11T21:51:44.615Z","etag":null,"topics":["javascript","result-type","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/badrap.png","metadata":{"files":{"readme":"README.md","changelog":null,"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":"2018-10-18T21:08:50.000Z","updated_at":"2025-03-21T19:40:52.000Z","dependencies_parsed_at":"2024-01-14T08:14:10.354Z","dependency_job_id":"18c6d7bd-fbae-4615-80b7-d3cf14fc39c6","html_url":"https://github.com/badrap/result","commit_stats":{"total_commits":62,"total_committers":3,"mean_commits":"20.666666666666668","dds":"0.032258064516129004","last_synced_commit":"88d93d29872402f67a015a4a1bd75d2ebe2b9294"},"previous_names":[],"tags_count":16,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/badrap%2Fresult","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/badrap%2Fresult/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/badrap%2Fresult/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/badrap%2Fresult/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/badrap","download_url":"https://codeload.github.com/badrap/result/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248635858,"owners_count":21137322,"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":["javascript","result-type","typescript"],"created_at":"2024-08-01T21:02:02.558Z","updated_at":"2025-04-12T21:33:47.411Z","avatar_url":"https://github.com/badrap.png","language":"TypeScript","readme":"# @badrap/result [![tests](https://github.com/badrap/result/workflows/tests/badge.svg)](https://github.com/badrap/result/actions?query=workflow%3Atests) [![npm](https://img.shields.io/npm/v/@badrap/result.svg)](https://www.npmjs.com/package/@badrap/result)\n\nA TypeScript result type taking cues from [Rust's Result](https://doc.rust-lang.org/std/result/) and [Haskell's Either](http://hackage.haskell.org/package/base/docs/Data-Either.html) types. It's goals are:\n\n- **Small, idiomatic API surface**: Mix and match parts from Rust's Result and Haskell's Either types, but modify them to make the experience TypeScript-y (TypeScriptic? TypeScriptalicious?). Of course this is pretty subjective.\n- **Coding errors should throw**: While **Result#map** and **Result#chain** together somewhat resemble [Promise#then](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then) but differ in that they don't implicitly wrap errors thrown in callbacks.\n- **Be ergonomic but safe**: Leverage TypeScript's type inference to make common cases simple while keeping type safety. This also helps to get a nice editor experience in e.g. Visual Studio Code.\n\n## Installation\n\n```sh\n$ npm i @badrap/result\n```\n\n## Usage\n\n```ts\nimport { Result } from \"@badrap/result\";\n```\n\n## API\n\n**Result\u003cT, E extends Error = Error\u003e** is a type that wraps either a value that is the result of a succesful computation and of type **T**, or an error of type **E** denoting a failed computation.\n\nThe type is actually an union of two types: **Result.Ok\u003cT, E\u003e** that wraps a success value and **Result.Err\u003cT, E\u003e** that wraps an error.\n\n### Result.ok / Result.err\n\n**Result.ok** returns a new **Result.Ok** wrapping the given value, while **Result.err** returns a new **Result.Err** wrapping the given error.\n\n```ts\nconst res = Result.ok(1);\nres.isOk; // true\n\nconst res = Result.err(new Error());\nres.isOk; // false\n\nconst res = Result.err(); // functionally equal to Result.err(new Error())\nres.isOk; // false\n```\n\n**Result.Ok** has an additional property **value** containing the wrapped value. Similarly, **Result.Err** has the property **error** containing the wrapped error. They can be accessed after asserting to TypeScript's type checker that it's safe to do so. The **isErr** and **isOk** properties (see below) are handy for this.\n\n```ts\nconst res = Math.random() \u003c 0.5 ? Result.ok(1) : Result.err(new Error(\"oh no\"));\n\nif (res.isErr) {\n  // TypeScript now knows that res is a Result.Err, and we can access res.error\n  res.error; // Error(\"oh no\")\n}\n\nif (res.isOk) {\n  // TypeScript now knows that res is a Result.Ok, and we can access res.value\n  res.value; // 1\n}\n```\n\n### Result#isOk / Result#isErr\n\n**Result#isOk** and **Result#isErr** are complementary readonly properties. **isOk** is `true` for **Result.Ok** and `false` for **Result.Err**.\n\n```ts\nconst ok = Result.ok(1);\nok.isOk; // true\n\nconst err = Result.err(new Error());\nerr.isOk; // false\n```\n\n**isErr** is the inverse of **isOk**: `false` for **Result.Ok** and `true` for **Result.Err**.\n\n```ts\nconst ok = Result.ok(1);\nok.isErr; // false\n\nconst err = Result.err(new Error());\nerr.isErr; // true\n```\n\n### Result#unwrap\n\nReturn the wrapped value for **Result.Ok** and throw the wrapped error for **Result.Err**.\nThis can be modified for providing functions to map the value and error to some value.\n\n```ts\nconst ok = Result.ok(1);\nconst err = Result.err(new Error(\"oh no\"));\n\nok.unwrap(); // 1\nerr.unwrap(); // throws Error(\"oh no\")\n\nok.unwrap((value) =\u003e value + 1); // 2\nerr.unwrap((value) =\u003e value + 2); // throws Error(\"oh no\")\n\nok.unwrap(\n  (value) =\u003e value + 1,\n  (error) =\u003e 0\n); // 2\nerr.unwrap(\n  (value) =\u003e value + 2,\n  (error) =\u003e 0\n); // 0\n```\n\nAs a small extra convenience the result types from the callbacks don't have to be the same.\nHere's an example [Koa.js](https://koajs.com/) handler demonstrating this, using an imaginary\n**validate** function that returns a **Result**:\n\n```ts\napp.use(async ctx =\u003e\n  await validate(ctx.request.body).unwrap(\n    async (value: any) =\u003e {\n      ...\n    },\n    error =\u003e {\n      ctx.status = 422;\n      ctx.body = {\n        message: \"validation failed\"\n      };\n    }\n  )\n);\n```\n\n### Result#map\n\nReturn a new **Result** where the given function/functions have been applied\nto the wrapped value and error.\n\n```ts\nconst ok = Result.ok(1);\nconst err = Result.err(new Error(\"oh no\"));\n\nok.map((value) =\u003e value + 1).unwrap(); // 2\nerr.map((value) =\u003e value + 1).unwrap(); // throws Error(\"oh no\")\n\nok.map(\n  (value) =\u003e value + 1,\n  (error) =\u003e new Error(\"mapped\")\n).unwrap(); // 2\nerr\n  .map(\n    (value) =\u003e value + 1,\n    (error) =\u003e new Error(\"mapped\")\n  )\n  .unwrap(); // throws Error(\"mapped\")\n```\n\n### Result#chain\n\n```ts\nconst ok = Result.ok(1);\nconst err = Result.err(new Error(\"oh no\"));\n\nok.chain((value) =\u003e Result.ok(value + 1)).unwrap(); // 2\nerr.chain((value) =\u003e Result.ok(value + 1)).unwrap(); // throws Error(\"oh no\")\n\nok.chain(\n  (value) =\u003e Result.ok(value + 1),\n  (error) =\u003e Result.ok(0)\n).unwrap(); // 2\nerr\n  .chain(\n    (value) =\u003e Result.ok(value + 1),\n    (error) =\u003e Result.ok(0)\n  )\n  .unwrap(); // 0\n```\n\n### Result.all\n\nReturn a new **Result** where the wrapped value is the\ncollection of the wrapped values of the input array.\n\n```ts\nResult.all([Result.ok(1), Result.ok(\"test\")]).unwrap(); // [1, \"test\"]\n```\n\nIf any of the input results wraps an error then that result is returned as-is.\n\n```ts\nResult.all([Result.ok(1), Result.err(new Error(\"oh no\"))]).unwrap(); // throws Error(\"oh no\")\n```\n\nNon-array objects can also be given as arguments. In that case the wrapped\noutput value is also an object.\n\n```ts\nResult.all({\n  x: Result.ok(1),\n  y: Result.ok(\"test\"),\n}).unwrap(); // { x: 1, y: \"test\" }\n```\n\n## License\n\nThis library is licensed under the MIT license. See [LICENSE](./LICENSE).\n","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbadrap%2Fresult","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbadrap%2Fresult","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbadrap%2Fresult/lists"}