{"id":15312724,"url":"https://github.com/everweij/typescript-result","last_synced_at":"2026-03-03T23:09:02.603Z","repository":{"id":65593619,"uuid":"289516305","full_name":"everweij/typescript-result","owner":"everweij","description":"A Result type inspired by Rust and Kotlin that leverages TypeScript's powerful type system to simplify error handling and make your code more readable and maintainable with full type safety.","archived":false,"fork":false,"pushed_at":"2025-01-01T15:44:15.000Z","size":330,"stargazers_count":180,"open_issues_count":2,"forks_count":7,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-05-12T10:12:47.399Z","etag":null,"topics":["error-handling","result","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/everweij.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"license.md","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":"2020-08-22T15:37:34.000Z","updated_at":"2025-05-12T00:55:23.000Z","dependencies_parsed_at":"2024-12-11T08:00:58.847Z","dependency_job_id":"c61613d4-8388-46da-8d63-b68cbed3f9b9","html_url":"https://github.com/everweij/typescript-result","commit_stats":{"total_commits":40,"total_committers":4,"mean_commits":10.0,"dds":"0.32499999999999996","last_synced_commit":"2beef687d0a67dd6c9b43f45d4143a8c179308c7"},"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/everweij%2Ftypescript-result","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/everweij%2Ftypescript-result/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/everweij%2Ftypescript-result/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/everweij%2Ftypescript-result/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/everweij","download_url":"https://codeload.github.com/everweij/typescript-result/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254453667,"owners_count":22073618,"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":["error-handling","result","typescript"],"created_at":"2024-10-01T08:38:22.409Z","updated_at":"2026-03-03T23:09:02.553Z","avatar_url":"https://github.com/everweij.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"\u003cimg alt=\"TypeScript Result logo\" width=\"84px\" src=\"./assets/typescript-result-logo.svg\" /\u003e\n\n# TypeScript Result\n\n[![NPM](https://img.shields.io/npm/v/typescript-result.svg)](https://www.npmjs.com/package/typescript-result)\n[![TYPESCRIPT](https://img.shields.io/badge/%3C%2F%3E-typescript-blue)](http://www.typescriptlang.org/)\n[![BUNDLEPHOBIA](https://badgen.net/bundlephobia/minzip/typescript-result)](https://bundlephobia.com/result?p=typescript-result)\n[![Weekly downloads](https://badgen.net/npm/dw/typescript-result)](https://badgen.net/npm/dw/typescript-result)\n\nA Result type inspired by Rust and Kotlin that leverages TypeScript's powerful type system to simplify error handling and make your code more readable and maintainable with full type safety.\n\n## Table of contents\n\n- [Getting started](#getting-started)\n- [Why should you use a result type?](#why-should-you-use-a-result-type)\n- [Why should you use this library?](#why-should-you-use-this-library)\n- [Guide](#guide)\n  - [A note on errors](#a-note-on-errors)\n  - [Creating a result](#creating-a-result)\n  - [Performing operations on a result](#performing-operations-on-a-result)\n  - [Unwrapping a result](#unwrapping-a-result)\n  - [Handling errors](#handling-errors)\n  - [Async operations](#async-operations)\n  - [Merging or combining results](#merging-or-combining-results)\n- [API Reference](#api-reference)\n\n## Getting started\n\n### Installation\n\nInstall using your favorite package manager:\n\n```bash\nnpm install typescript-result\n```\n\n### Requirements\n\n#### Typescript\n\nTechnically Typescript with version `4.8.0` or higher should work, but we recommend using version \u003e= `5` when possible.\n\nAlso it is important that you have `strict` or `strictNullChecks` enabled in your `tsconfig.json`:\n\n```json\n{\n  \"compilerOptions\": {\n    \"strict\": true\n  }\n}\n```\n\n#### Node\n\nTested with Node.js version `16` and higher.\n\n### Example\n\nReading a JSON config file and validating its contents:\n\n```typescript\nimport { Result } from \"typescript-result\";\nimport fs from \"node:fs/promises\";\n\nclass IOError extends Error {\n  readonly type = \"io-error\";\n}\n\nclass ParseError extends Error {\n  readonly type = \"parse-error\";\n}\n\nclass ValidationError extends Error {\n  readonly type = \"validation-error\";\n}\n\nfunction readFile(path: string) {\n  return Result.try(\n    () =\u003e fs.readFile(path, \"utf-8\"),\n    (error) =\u003e new IOError(`Unable to read file '${path}'`, { cause: error })\n  );\n}\n\nconst isObject = (value: unknown): value is Record\u003cstring, unknown\u003e =\u003e\n  typeof value === \"object\" \u0026\u0026 value !== null;\n\nconst isString = (value: unknown): value is string =\u003e typeof value === \"string\";\n\nfunction getConfig(value: unknown) {\n  if (!isObject(value)) {\n    return Result.error(new ValidationError(\"Invalid config file\"));\n  }\n  if (!value.name || !isString(value.name)) {\n    return Result.error(new ValidationError(\"Missing or invalid 'name' field\"));\n  }\n  if (!value.version || !isString(value.version)) {\n    return Result.error(\n      new ValidationError(\"Missing or invalid 'version' field\")\n    );\n  }\n\n  return Result.ok({ name: value.name, version: value.version });\n}\n\nconst message = await readFile(\"./config.json\")\n  .mapCatching(\n    (contents) =\u003e JSON.parse(contents),\n    (error) =\u003e new ParseError(\"Unable to parse JSON\", { cause: error })\n  )\n  .map((json) =\u003e getConfig(json))\n  .fold(\n    (config) =\u003e\n      `Successfully read config: name =\u003e ${config.name}, version =\u003e ${config.version}`,\n\n    (error) =\u003e {\n      switch (error.type) {\n        case \"io-error\":\n          return \"Please check if the config file exists and is readable\";\n        case \"parse-error\":\n          return \"Please check if the config file contains valid JSON\";\n        case \"validation-error\":\n          return error.message;\n      }\n    }\n  );\n```\n\nThere's also an example repository available [here](https://github.com/everweij/typescript-result-example) that demonstrates how you could potentially use this library in the context of a web API.\n\n## Why should you use a result type?\n\n### Errors as values\n\nThe Result type is a product of the ‘error-as-value’ movement, which in turn has its roots in functional programming. When throwing exceptions, all errors are treated equally and behave differently compared to the normal flow of the program. Instead, we like to make a distinction between expected errors and unexpected errors, and make the expected errors part of the normal flow of the program. By explicitly defining that a piece of code can either fail or succeed using the Result type, we can leverage TypeScript's powerful type system to keep track of everything that can go wrong in our code, and let it correct us when we overlook certain scenarios by performing exhaustive checks. This makes our code more type-safe, easier to maintain, and more transparent.\n\n### Ergonomic error handling\n\nThe goal is to keep the effort in using this library as light as possible, with a relatively small API surface. We don't want to introduce a whole new programming model where you would have to learn a ton of new concepts. Instead, we want to build on top of the existing features and best practices of the language, and provide a simple and intuitive API that is easy to understand and use. It also should be easy to incrementally adopt within existing codebase.\n\n## Why should you use this library?\n\nThere are already a few quality libraries out there that provide a Result type or similar for TypeScript. We believe that there are two reasons why you should consider using this library.\n\n### Async support\n\nResult instances that are wrapped in a Promise can be painful to work with, because you would have to `await` every async operation before you can _chain_ next operations (like 'map', 'fold', etc.). To solve this and to make your code more ergonomic we provide an `AsyncResult` that is essentially a regular Promise containing a `Result` type, along with a couple of methods to make it easier to chain operations without having to assign the intermediate results to a variable or having to use `await` for each async operation.\n\nSo instead of writing:\n\n```typescript\nconst firstAsyncResult = await someAsyncFunction1();\nif (firstAsyncResult.isOk()) {\n  const secondAsyncResult = await someAsyncFunction2(firstAsyncResult.value);\n  if (secondAsyncResult.isOk()) {\n    const thirdAsyncResult = await someAsyncFunction3(secondAsyncResult.value);\n    if (thirdAsyncResult.isOk()) {\n      // do something\n    } else {\n      // handle error\n    }\n  } else {\n    // handle error\n  }\n} else {\n  // handle error\n}\n```\n\nYou can write:\n\n```typescript\nconst result = await Result.fromAsync(someAsyncFunction1())\n  .map((value) =\u003e someAsyncFunction2(value))\n  .map((value) =\u003e someAsyncFunction3(value))\n  .fold(\n    (value) =\u003e {\n      // do something on success\n    },\n    (error) =\u003e {\n      // handle error\n    }\n  );\n```\n\nYou rarely have to deal with `AsyncResult` directly though, because this library will automatically convert the result of an async operation to an `AsyncResult` when needed, and since the API's are almost identical in shape, there's a big chance you wouldn't even notice you're using a `AsyncResult` under the hood. Let's look at an example what this means in practice:\n\n```typescript\n// start with a sync value -\u003e Result\u003cnumber, never\u003e\nconst result = await Result.ok(12)\n  // map the value to a Promise -\u003e AsyncResult\u003cnumber, never\u003e\n  .map((value) =\u003e Promise.resolve(value * 2)) // \n  // map async to another result -\u003e AsyncResult\u003cstring, ValidationError\u003e\n  .map(async (value) =\u003e {\n    if (value \u003c 10) {\n      return Result.error(new ValidationError(\"Value is too low\"));\n    }\n\n    return Result.ok(\"All good!\");\n  })\n  // unwrap the result -\u003e Promise\u003cstring\u003e;\n  .getOrElse((error) =\u003e error.message);\n```\n\n### _Full_ type safety without a lot of boilerplate\n\nThis library is able to track all possible outcomes simply by using type inference. Of course, there are edge cases, but most of the time all you have to do is to simply return `Result.ok()` or `Result.error()`, and the library will do the rest for you.\nIn the example below, Typescript will complain that not all code paths return a value. Rightfully so, because we forgot to implement the case where there is not enough stock:\n\n```typescript\nclass NotEnoughStockError extends Error {\n  readonly type = \"not-enough-stock\";\n}\n\nclass InsufficientBalanceError extends Error {\n  readonly type = \"insufficient-balance\";\n}\n\nfunction order(basket: Basket, stock: Stock, account: Account) {\n  if (basket.getTotalPrice() \u003e account.balance) {\n    return Result.error(new InsufficientBalanceError());\n  }\n\n  if (!stock.hasEnoughStock(basket.getProducts())) {\n    return Result.error(new NotEnoughStockError());\n  }\n\n  const order: Order = { /* skipped for brevity */ }\n\n  return Result.ok(order);\n}\n\nfunction handleOrder(products: Product[], userId: number) {\n  /* skipped for brevity  */\n\n  return order(basket, stock, account).fold(\n    () =\u003e ({\n      status: 200,\n      body: \"Order placed successfully\",\n    }),\n    (error) =\u003e { // TS-Error: Not all code paths return a value\n      switch(error.type) {\n        case \"insufficient-balance\":\n          return {\n            status: 400,\n            body: \"Insufficient balance\",\n          }\n      }\n    }\n  );\n}\n```\n\n## Guide\n\n### A note on errors\n\nErrors are a fundamental part of the Result type. This library does not have a strong opinion on what your errors should look like; they can be any value, like a string, number, object, etc. Usually though, people tend to use instances of the `Error` class or any custom errors by subclassing the `Error` class.\n\nThere's only one thing to keep in mind when it comes to using custom errors that extends the `Error` class: in certain circumstances, like inferring errors of a result type, TypeScript tends to unify types that look similar. This means that in the example below, TypeScript will infer the error type of the result to be `Error` instead of `ErrorA | ErrorB`. This is because TypeScript does not have a way to distinguish between the two errors, since they are both instances of the `Error` class.\n\n```typescript\nclass ErrorA extends Error {}\nclass ErrorB extends Error {}\n\nfunction example() {\n  if (condition) {\n    return Result.error(new ErrorA());\n  }\n\n  return Result.error(new ErrorB());\n}\n\nconst result = example();\nif (result.isError()) {\n  // TypeScript infers that result.error is of type Error, and not ErrorA | ErrorB\n  console.error(result.error);\n}\n```\n\nTo mitigate this, you can add a property on your custom errors, a so-called discriminant field, that makes it easier for TypeScript to distinguish between the different error types. In the example below, TypeScript will infer the error type of the result to be `ErrorA | ErrorB`:\n\n```typescript\nclass ErrorA extends Error {\n  readonly type = \"error-a\";\n}\nclass ErrorB extends Error {\n  readonly type = \"error-b\";\n}\n\nfunction example() {\n  if (condition) {\n    return Result.error(new ErrorA());\n  }\n\n  return Result.error(new ErrorB());\n}\n\nconst result = example();\nif (result.isError()) {\n  console.error(result.error); // ErrorA | ErrorB\n}\n```\n\nAlthough we agree that this might be a bit cumbersome, it is a small price to pay for the benefits that you get in return. For consistency, we recommend to always add a `readonly type` property to your custom errors.\n\n### Creating a result\n\n#### Basic usage\n\nThe most common way to create a result is by using the [`Result.ok`](#resultokvalue) and [`Result.error`](#resulterrorerror) static methods.\n\nThe example below produces a result which contains either the outcome of the division or a `DivisionByZeroError` error.\n\n```ts\nfunction divide(a: number, b: number) {\n  if (b === 0) {\n    return Result.error(new DivisionByZeroError(`Cannot divide ${a} by zero`));\n  }\n\n  return Result.ok(a / b);\n}\n```\n\nNote that we didn't specify an explicit return type for the `divide` function. In most cases TypeScript is smart enough to infer the result types most of the times for you. In case of the example above, the return type gets inferred to `Result\u003cnumber, DivisionByZeroError\u003e`. There are good reasons to specify the return type explicitly (e.g. clarity, readability, etc.), but in general it is not technically a necessity and therefore up to you to decide to define your returns explicit or not.\n\nAlso note that when using `Result.ok` it is optional to provide a value, simply because not all operations produce a value.\n\n```ts\n// this is fine\nconst result = Result.ok(); // Result\u003cvoid, never\u003e\n```\n\n#### Using `Result.try` and `Result.wrap`\n\n[`Result.try`](#resulttryfn-transform) is a convenient way to wrap code that might throw an error. The method will catch any exceptions that might be thrown and encapsulate them in a failed result. This is especially useful when you want to work with existing or external functions that might throw exceptions. You can often replace traditional try-catch blocks by wrapping the code in `Result.try`:\n\n```ts\n// Using try-catch\nlet result: Result\u003cvoid, Error\u003e;\ntry {\n  fs.writeFileSync(\"file.txt\", \"Hello, World!\", \"utf-8\");\n  result = Result.ok();\n} catch (error) {\n  result = Result.error(error);\n}\n\n// Using Result.try\nconst result = Result.try(() =\u003e fs.writeFileSync(\"file.txt\", \"Hello, World!\", \"utf-8\"));\n```\n\nHere, we are using Node's `fs` module to write a file to disk. The `writeFileSync` method might throw an error if something goes wrong. You might not have the correct permissions for instance, or you ran out of disk space. By using `Result.try`, we can catch the error and encapsulate it in a failed result.\n\nOptionally, you can provide a second argument to `Result.try` which is a callback that allows you to transform the caught error into a more meaningful error. This is useful when you want to provide more context or when you want to wrap the error in a custom error type.\n\n```ts\nconst result = Result.try(\n\t() =\u003e fs.writeFileSync(\"file.txt\", \"Hello, World!\", \"utf-8\"),\n\t(error) =\u003e new IOError(\"Failed to save file\", { cause: error }),\n);\n```\n\nAdditionally, you can use [`Result.wrap`](#resultwrapfn) to wrap a function and return a new function that returns a result. The main difference compared to `Result.try` is that `Result.wrap` returns a function, while `Result.try` executes the function immediately. \n\n```ts\nconst safeWriteFile = Result.wrap(fs.writeFileSync);\n\nconst result = safeWriteFile(\"file.txt\", \"Hello, World!\", \"utf-8\"); // Result\u003cvoid, Error\u003e\n```\n\n### Performing operations on a result\n\nHaving a result is one thing, but in many cases, you also want to do something with it. This library provides a set of methods that lets you interact with the instance of a result in various ways.\n\n#### Chaining operations\n\nSimilar to arrays and promises, you can also chain operations on a result. The main benefit of chaining operations is that you can keep your code compact, concise and readable, without having to assign intermediate results to variables. Let's look at an example:\n\n```ts\n// Without chaining\nconst resultA = someOperation();\nif (resultA.isOk()) {\n  const resultB = anotherOperation(resultA.value);\n  if (resultB.isOk()) {\n    const resultC = yetAnotherOperation(resultB.value);\n    if (resultC.isOk()) {\n      // do something\n    } else {\n      // handle error\n    }\n  } else {\n    // handle error\n  }\n} else {\n  // handle error\n}\n\n// With chaining\nconst result = someOperation()\n  .map((value) =\u003e anotherOperation(value))\n  .map((value) =\u003e yetAnotherOperation(value))\n\nif (result.isOk()) {\n  // do something\n} else {\n  // handle error\n}\n```\n\nThe chained version is more concise and makes it easier to follow the flow of the program. Moreover, it allows us to _centralize_ error handling at the end of the flow. This is possible because all transformative operations produce new results which carry over any errors that might have occurred earlier in the chain.\n\n#### Transform: `map`, `mapCatching`, `recover`, `recoverCatching`, `mapError`\n\nBoth [`map`](#maptransformfn) and [`recover`](#recoveronfailure) behave very similar in the sense that they transform a result using function provided by the user into a new result. The main difference is that `map` is used to transform a successful result, while `recover` is used to transform a failed result.\n\nThe difference between the 'catching' variants is that they catch any exceptions that might be thrown inside the transformation function and encapsulate them in a failed result. So why would you not always use the 'catching' variants? It might be useful to make a distinction between exceptions that are expected and unexpected. If you _expect_ an exception to be thrown, like in the case of writing a file to disk, you might want to handle this use case. If you _don't expect_ an exception to be thrown, like in the case of saving something to a database, you might _not_ want to catch the exception and let the exception bubble up or even terminate the application.\n\nThere's a subtle difference with `mapCatching` however. It takes an optional second argument which is a function that lets you transform any caught exception that was thrown inside the transformation function. This is useful when you want to provide more context or when you want to wrap the error in a custom error type.\n\n```ts\nreadFile(\"source.txt\")\n  .mapCatching(\n    (contents) =\u003e writeFile(\"destination.txt\", contents.toUpperCase()),\n    (error) =\u003e new IOError(\"Failed to write file\", { cause: error })\n  )\n```\n\nBoth `map` and `recover` are very flexible when it comes to the returning value of the transformation function. You can return a literal value, a new result, or even a promise that resolves to a value or a result. Other similar result-like libraries might have specific methods for each of thee use cases (e.g. `flatMap`, `chain`, etc.) and can be considered more strict. However, we like the approach of a smaller API surface with more flexibility.\n\nAll transformations below produce the same type of result (`Result\u003cnumber, Error\u003e`, with the exception of the async transformations which produce an `AsyncResult\u003cnumber, Error\u003e`):\n```ts\nsomeOperation() // Result\u003cnumber, Error\u003e\n  .map((value) =\u003e value * 2) // Result\u003cnumber, Error\u003e \n  .map((value) =\u003e Result.ok(value * 2)) // Result\u003cnumber, Error\u003e\n  .map((value) =\u003e Promise.resolve(value * 2)) // AsyncResult\u003cnumber, Error\u003e;\n  .map(async (value) =\u003e value * 2) // AsyncResult\u003cnumber, Error\u003e;\n  .map(async (value) =\u003e Result.ok(value * 2)) // AsyncResult\u003cnumber, Error\u003e;\n```\n\n`recover` is especially useful when you want to fall back to another scenario when a previous operation fails. In the example below, we try to persist an item in the database. If that fails, we fall back to persisting the item locally.\n\n```ts\nfunction persistInDB(item: Item): Result\u003cItem, DbError\u003e {\n  // implementation\n};\nfunction persistLocally(item: Item): Result\u003cItem, IOError\u003e {\n  // implementation\n};\n\npersistInDB(item).recover(() =\u003e persistLocally(item)); // Result\u003cItem, IOError\u003e\n```\n\nNote that after a recovery, any previous errors that might have occurred are _forgotten_. This is because when using `recover` you are essentially starting with a clean slate. In the example above we can assume that the `DbError` has been taken care of and therefore it has been removed from the final result. `IOError` on te other hand is still a possibility because it might occur after the recovery.\n\nLastly, you can use `mapError` to transform the error of a failed result. This is especially useful when you want to transform the error into a different error type, or when you want to provide more context to the error:\n\n```ts\nResult.try(() =\u003e fs.readFileSync(\"source.txt\", \"utf-8\"))\n  .mapCatching(contents =\u003e fs.writeFileSync(\"destination.txt\", contents.toUpperCase(), \"utf-8\"))\n  .mapError((error) =\u003e new IOError(\"Failed to transform file\", { cause: error }));\n  // Result\u003cvoid, IOError\u003e\n```\n\n#### Side-effects: `onSuccess`, `onFailure`\n\nSometimes you want to perform side-effects without modifying the result itself. This is where `onSuccess` and `onFailure` come in handy. Both methods allow you to run a callback function when the result is successful or when the result represents a failure. The main difference is that `onSuccess` is used for successful results, while `onFailure` is used for failed results. Both methods return the original instance of the result, so you can continue chaining other operations.\n\nIn the example below, we log a message when an operation is successful and when it fails:\n\n```ts\nsomeOperation()\n  .onSuccess((value) =\u003e console.log(\"Operation succeeded with value\", value))\n  .onFailure((error) =\u003e console.error(\"Operation failed with error\", error));\n```\n\n### Unwrapping a result\n\nAt some point in the flow of your program, you want to retrieve the value of a successful result or \nthe error of a failed result. There are a couple of ways to do this, depending on your use case.\n\n#### Using `toTuple()` to destructure the result\n\n`toTuple()` returns the result in a tuple format where the first element is the _value_ and the second element is the _error_. We can leverage TypeScript's narrowing capabilities to infer the correct type of the value or error by doing a simple conditional check:\n\n```ts\ndeclare const result: Result\u003cnumber, IOError\u003e;\n\nconst [value, error] = result.toTuple();\n\nif (value) {\n  // at this point the value must be a number\n} else {\n  // error must be an instance of IOError\n}\n```\n\nAnother approach is to return early when the result is a failure. This is a pattern common in the Go language:\n\n```ts\nconst [value, error] = result.toTuple();\n\nif (error) {\n  return Result.error(error);\n}\n\nreturn Result.ok(value * 2);\n```\n\nNote that in this example `Result.map` would be a better fit, but it illustrates the point. A more realistic example could be the handling of a request in a web API:\n\n```ts\nfunction handleRoute(id: number) {\n  const [value, error] = performOperation(id).toTuple();\n\n  if (error) {\n    switch (error.type) {\n      case \"not-found\":\n        return {\n          status: 404,\n          body: \"Not found\",\n        };\n      case \"unauthorized\":\n        return {\n          status: 401,\n          body: \"Unauthorized\",\n        };\n      default:\n        return {\n          status: 500,\n          body: \"Internal server error\",\n        };\n    }\n  }\n\n  return {\n    status: 200,\n    body: value,\n  }\n}\n```\n\n#### Narrowing down the type using `isOk()` and `isError()`\n\nAnother imperative approach is to use the `isOk()` and `isError()` methods to narrow down the type of the result:\n\n```ts\nif (result.isOk()) {\n  // TS infers that result.value is defined\n  console.log(result.value);\n} else if (result.isError()) {\n  // TS infers that result.error is defined\n  console.error(result.error);\n}\n```\n\nIf you do not use the type guards, TypeScript will infer the value or error as `T | undefined`. However, there is one exception to this rule: if a result has a error-type of `never`, it is safe to assume that the result can only be successful. Similarly, if the value-type is `never`, it is safe to assume that the result can only be a failure.\n\n```ts\nconst resultA = Result.ok(42); // Result\u003cnumber, never\u003e\nresultA.value; // can only be a `number`, since the error-type is `never`\n\nconst resultB = Result.error(new Error(\"Something went wrong\")); // Result\u003cnever, Error\u003e\nresultB.value; // can only by `undefined`, since the value-type is `never`\nresultB.error; // can only be an `Error`, since the value-type is `never`\n```\n\n#### Folding a result using `fold`\n\nThe `fold` method is a more functional approach to unwrapping a result. It allows you to provide two callbacks: one for the successful case and one for the failure case. The `fold` method will execute the appropriate callback based on the outcome of the result. Using `fold` is especially useful when you want to return the a single 'thing' based on the outcome of the result, for example when you want to return a response object:\n\n```ts\nfunction handleRoute(id: number) {\n  return performOperation(id).fold(\n    (value) =\u003e ({\n      status: 200,\n      body: value,\n    }),\n    (error) =\u003e {\n      switch (error.type) {\n        case \"not-found\":\n          return {\n            status: 404,\n            body: \"Not found\",\n          };\n        case \"unauthorized\":\n          return {\n            status: 401,\n            body: \"Unauthorized\",\n          };\n        default:\n          return {\n            status: 500,\n            body: \"Internal server error\",\n          };\n      }\n    }\n  );\n}\n```\n\n#### using 'getter' functions\n\nPlease consult the [API Reference](#api-reference) for a full list of available methods:\n- [`errorOrNull`](#errorornull-1)\n- [`getOrNull`](#getornull-1)\n- [`getOrDefault`](#getordefaultdefaultvalue-1)\n- [`getOrElse`](#getorelseonfailure-1)\n\n### Handling errors\n\nSee the note on [errors](#a-note-on-errors) for more context.\n\nWhen using custom errors together with a `type` field to distinguish between different error types, you can use conditional checks like 'if-else' or `switch` statements to handle different error types.\n\nIn order to perform exhaustive checks you can rely on the [`noImplicitReturns`](https://www.typescriptlang.org/tsconfig/#noImplicitReturns) compiler option when you are inside the context of a function and you are conditionally returning a value based on the `type` of the error:\n\n```ts\nclass ErrorA extends Error {\n  readonly type = \"error-a\";\n}\n\nclass ErrorB extends Error {\n  readonly type = \"error-b\";\n}\n\ndeclare const result: Result\u003cnumber, ErrorA | ErrorB\u003e;\n\nresult.fold(\n  (value) =\u003e /* do something */,\n  (error) =\u003e { // TS-Error: Not all code paths return a value\n    switch (error.type) {\n      case \"error-a\":\n        return /* something */;\n    }\n  }\n)\n```\n\nAlternatively, you can manually perform exhaustive checks by checking for `never` using a `default` case in a `switch` statement, or the `else` branch in an `if-else` statement:\n\n```ts\nclass ErrorA extends Error {\n  readonly type = \"error-a\";\n}\n\nclass ErrorB extends Error {\n  readonly type = \"error-b\";\n}\n\ndeclare const result: Result\u003cnumber, ErrorA | ErrorB\u003e;\n\nif (result.isError()) {\n  const error = result.error;\n  if (error.type === \"error-a\") {\n    // handle error-a\n  } else if (error.type === \"error-b\") {\n    // handle error-b\n  } else {\n    error satisfies never;\n  }\n}\n```\n\nBecause this pattern is so common, this library exposes a little utility function called `assertUnreachable`:\n\n```ts\nimport { assertUnreachable } from \"typescript-result\";\n\nif (result.isError()) {\n  const error = result.error;\n  if (error.type === \"error-a\") {\n    // handle error-a\n  } else if (error.type === \"error-b\") {\n    // handle error-b\n  } else {\n    assertUnreachable(error)\n  }\n}\n```\n\nWhen not all code paths are considered, the `assertUnreachable` function will start to complain. At runtime it will also throw an error when the `default` case is reached.\n\n### Async operations\n\nSee [Async support](#async-support) for more context.\n\nBecause it can be quite cumbersome to work with results that are wrapped in a promise, we provide an `AsyncResult` type that is essentially a regular promise that contains a `Result` type, along with most of the methods that are available on the regular `Result` type. This makes it easier to chain operations without having to assign the intermediate results to a variable or having to use `await` for each async operation.\n\nThere are of course plenty of scenarios where an async function returns a `Result` (`Promise\u003cResult\u003c*, *\u003e\u003e`). In these cases, you can use the `fromAsync` and `fromAsyncCatching` methods to convert the promise to an `AsyncResult`, and continue chaining operations:\n\n```ts\nasync function someAsyncOperation(): Promise\u003cResult\u003cnumber, Error\u003e\u003e {\n  return Result.ok(42);\n}\n\nconst result = await Result.fromAsync(someAsyncOperation())\n  .map((value) =\u003e value * 2)\n  // etc...\n```\n\n### Merging or combining results\n\nIn some cases you might want to combine multiple results into a single result. This can be done using the [`Result.all`](#resultallitems) and [`Result.allCatching`](#resultallcatchingitems) methods. The `Result.all` method will return a successful result if all results are successful, otherwise it will return the first error that occurred. This is especially useful when you want to run multiple independent operations and bundle the outcome into a single result:\n\n```ts\ndeclare function createTask(name: string): Result\u003cTask, IOError\u003e;\n\nconst tasks = [\"task-a\", \"task-b\", \"task-c\"];\nconst result = Result.all(...tasks.map(createTask)); // Result\u003cTask[], IOError\u003e\n```\n\n# API Reference\n\n## Table of contents\n\n- [Result](#result)\n  - Properties\n    - [isResult](#isresult)\n    - [value](#value)\n    - [error](#error)\n  - Instance methods\n    - [isOk()](#isok)\n    - [isError()](#iserror)\n    - [toTuple()](#totuple)\n    - [errorOrNull()](#errorornull)\n    - [getOrNull()](#getornull)\n    - [getOrDefault(defaultValue)](#getordefaultdefaultvalue)\n    - [getOrElse(onFailure)](#getorelseonfailure)\n    - [getOrThrow()](#getorthrow)\n    - [fold(onSuccess, onFailure)](#foldonsuccess-onfailure)\n    - [onFailure(action)](#onfailureaction)\n    - [onSuccess(action)](#onsuccessaction)\n    - [map(transformFn)](#maptransformfn)\n    - [mapCatching(transformFn, transformErrorFn?)](#mapcatchingtransformfn-transformerrorfn)\n    - [mapError(transformFn)](#maperrortransformfn)\n    - [recover(onFailure)](#recoveronfailure)\n    - [recoverCatching(onFailure)](#recovercatchingonfailure)\n  - Static methods\n    - [Result.ok(value)](#resultokvalue)\n    - [Result.error(error)](#resulterrorerror)\n    - [Result.isResult(possibleResult)](#resultisresultpossibleresult)\n    - [Result.isAsyncResult(possibleAsyncResult)](#resultisasyncresultpossibleasyncresult)\n    - [Result.all(items)](#resultallitems)\n    - [Result.allCatching(items)](#resultallcatchingitems)\n    - [Result.wrap(fn)](#resultwrapfn)\n    - [Result.try(fn, [transform])](#resulttryfn-transform)\n    - [Result.fromAsync(promise)](#resultfromasyncpromise)\n    - [Result.fromAsyncCatching(promise)](#resultfromasynccatchingpromise)\n    - [Result.assertOk(result)](#resultassertokresult)\n    - [Result.assertError(result)](#resultasserterrorresult)\n- [AsyncResult](#asyncresult)\n  - Properties\n    - [isAsyncResult](#isasyncresult)\n  - Instance methods\n    - [toTuple()](#totuple-1)\n    - [errorOrNull()](#errorornull-1)\n    - [getOrNull()](#getornull-1)\n    - [getOrDefault(defaultValue)](#getordefaultdefaultvalue-1)\n    - [getOrElse(onFailure)](#getorelseonfailure-1)\n    - [getOrThrow()](#getorthrow-1)\n    - [fold(onSuccess, onFailure)](#foldonsuccess-onfailure-1)\n    - [onFailure(action)](#onfailureaction-1)\n    - [onSuccess(action)](#onsuccessaction-1)\n    - [map(transformFn)](#maptransformfn-1)\n    - [mapCatching(transformFn, transfornErrorFn?)](#mapcatchingtransformfn-transformerrorfn-1)\n    - [mapError(transformFn)](#maperrortransformfn-1)\n    - [recover(onFailure)](#recoveronfailure-1)\n    - [recoverCatching(onFailure)](#recovercatchingonfailure-1)\n\n## Result\n\nRepresents the outcome of an operation that can either succeed or fail.\n\n```ts\nclass Result\u003cValue, Error\u003e {}\n```\n\n### isResult\n\nUtility getter that checks if the current instance is a `Result`.\n\n### value\n\nRetrieves the encapsulated value of the result when the result is successful.\n\n\u003e [!NOTE]\n\u003e You can use [`Result.isOk()`](#isok) to narrow down the type to a successful result.\n\n#### Example\nobtaining the value of a result, without checking if it's successful\n```ts\ndeclare const result: Result\u003cnumber, Error\u003e;\n\nresult.value; // number | undefined\n```\n\n#### Example\nobtaining the value of a result, after checking for success\n```ts\ndeclare const result: Result\u003cnumber, Error\u003e;\n\nif (result.isOk()) {\n  result.value; // number\n}\n```\n\n### error\n\nRetrieves the encapsulated error of the result when the result represents a failure.\n\n\u003e [!NOTE]\n\u003e You can use [`Result.isError()`](#iserror) to narrow down the type to a failed result.\n\n#### Example\nobtaining the value of a result, without checking if it's a failure\n\n```ts\ndeclare const result: Result\u003cnumber, Error\u003e;\n\nresult.error; // Error | undefined\n```\n\n#### Example\nobtaining the error of a result, after checking for failure\n```ts\ndeclare const result: Result\u003cnumber, Error\u003e;\n\nif (result.isError()) {\n  result.error; // Error\n}\n```\n\n### isOk()\n\nType guard that checks whether the result is successful.\n\n**returns** `true` if the result is successful, otherwise `false`.\n\n#### Example\nchecking if a result is successful\n```ts\ndeclare const result: Result\u003cnumber, Error\u003e;\n\nif (result.isOk()) {\n  result.value; // number\n}\n```\n\n### isError()\n\nType guard that checks whether the result is successful.\n\n**returns** `true` if the result represents a failure, otherwise `false`.\n\n#### Example\nchecking if a result represents a failure\n```ts\ndeclare const result: Result\u003cnumber, Error\u003e;\n\nif (result.isError()) {\n  result.error; // Error\n}\n```\n\n### toTuple()\n\n**returns** the result in a tuple format where the first element is the value and the second element is the error.\n\nIf the result is successful, the error will be `null`. If the result is a failure, the value will be `null`.\nThis method is especially useful when you want to destructure the result into a tuple and use TypeScript's narrowing capabilities.\n\n#### Example\nNarrowing down the type using destructuring\n```ts\ndeclare const result: Result\u003cnumber, ErrorA\u003e;\n\nconst [value, error] = result.toTuple();\n\nif (error) {\n  // error is ErrorA\n} else {\n  // at this point the value must be a number\n}\n```\n\n### errorOrNull()\n\n**returns** the encapsulated error if the result is a failure, otherwise `null`.\n\n### getOrNull()\n\n**returns** the encapsulated value if the result is successful, otherwise `null`.\n\n### getOrDefault(defaultValue)\n\nRetrieves the value of the result, or a default value if the result is a failure.\n\n#### Parameters\n\n- `defaultValue` The value to return if the result is a failure.\n\n**returns** The encapsulated value if the result is successful, otherwise the default value.\n\n#### Example\nobtaining the value of a result, or a default value\n```ts\ndeclare const result: Result\u003cnumber, Error\u003e;\n\nconst value = result.getOrDefault(0); // number\n```\n\n#### Example\nusing a different type for the default value\n```ts\ndeclare const result: Result\u003cnumber, Error\u003e;\n\nconst value = result.getOrDefault(\"default\"); // number | string\n```\n\n### getOrElse(onFailure)\n\nRetrieves the value of the result, or transforms the error using the `onFailure` callback into a value.\n\n#### Parameters\n\n- `onFailure` callback function which allows you to transform the error into a value. The callback can be async as well.\n\n**returns** either the value if the result is successful, or the transformed error.\n\n#### Example\ntransforming the error into a value\n```ts\ndeclare const result: Result\u003cnumber, Error\u003e;\n\nconst value = result.getOrElse((error) =\u003e 0); // number\n```\n\n#### Example\nusing an async callback\n```ts\nconst value = await result.getOrElse(async (error) =\u003e 0); // Promise\u003cnumber\u003e\n```\n\n### getOrThrow()\n\nRetrieves the value of the result, or throws an error if the result is a failure.\n\n**returns** The value if the result is successful.\n\n**throws** the encapsulated error if the result is a failure.\n\n#### Example\nobtaining the value of a result, or throwing an error\n```ts\ndeclare const result: Result\u003cnumber, Error\u003e;\n\nconst value = result.getOrThrow(); // number\n```\n\n### fold(onSuccess, onFailure)\n\nReturns the result of the `onSuccess` callback when the result represents success or\nthe result of the `onFailure` callback when the result represents a failure.\n\n\u003e [!NOTE]\n\u003e Any exceptions that might be thrown inside the callbacks are not caught, so it is your responsibility\n\u003e to handle these exceptions\n\n#### Parameters\n\n- `onSuccess` callback function to run when the result is successful. The callback can be async as well.\n- `onFailure` callback function to run when the result is a failure. The callback can be async as well.\n\n**returns** * the result of the callback that was executed.\n\n#### Example\nfolding a result to a response-like object\n\n```ts\ndeclare const result: Result\u003cUser, NotFoundError | UserDeactivatedError\u003e;\n\nconst response = result.fold(\n  (user) =\u003e ({ status: 200, body: user }),\n  (error) =\u003e {\n    switch (error.type) {\n      case \"not-found\":\n        return { status: 404, body: \"User not found\" };\n      case \"user-deactivated\":\n        return { status: 403, body: \"User is deactivated\" };\n    }\n  }\n);\n```\n\n### onFailure(action)\n\nCalls the `action` callback when the result represents a failure. It is meant to be used for\nside-effects and the operation does not modify the result itself.\n\n#### Parameters\n\n- `action` callback function to run when the result is a failure. The callback can be async as well.\n\n**returns** the original instance of the result.\n\n\u003e [!NOTE]\n\u003e Any exceptions that might be thrown inside the `action` callback are not caught, so it is your responsibility\n\u003e to handle these exceptions\n\n#### Example\nadding logging between operations\n```ts\ndeclare const result: Result\u003cnumber, Error\u003e;\n\nresult\n  .onFailure((error) =\u003e console.error(\"I'm failing!\", error))\n  .map((value) =\u003e value 2); // proceed with other operations\n```\n\n### onSuccess(action)\n\nCalls the `action` callback when the result represents a success. It is meant to be used for\nside-effects and the operation does not modify the result itself.\n\n#### Parameters\n\n- `action` callback function to run when the result is successful. The callback can be async as well.\n\n**returns** * the original instance of the result. If the callback is async, it returns a new [`AsyncResult`](#asyncresult) instance.\n\n\u003e [!NOTE]\n\u003e Any exceptions that might be thrown inside the `action` callback are not caught, so it is your responsibility\n\u003e to handle these exceptions\n\n#### Example\nadding logging between operations\n```ts\ndeclare const result: Result\u003cnumber, Error\u003e;\n\nresult\n  .onSuccess((value) =\u003e console.log(\"I'm a success!\", value))\n  .map((value) =\u003e value 2); // proceed with other operations\n```\n\n#### Example\nusing an async callback\n```ts\ndeclare const result: Result\u003cnumber, Error\u003e;\n\nconst asyncResult = await result.onSuccess(async (value) =\u003e someAsyncOperation(value));\n```\n\n### map(transformFn)\n\nTransforms the value of a successful result using the `transform` callback.\nThe `transform` callback can also return other `Result` or [`AsyncResult`](#asyncresult) instances,\nwhich will be returned as-is (the `Error` types will be merged).\nThe operation will be ignored if the result represents a failure.\n\n#### Parameters\n\n- `transformFn` callback function to transform the value of the result. The callback can be async as well.\n\n**returns** * a new [`Result`](#result) instance with the transformed value, or a new [`AsyncResult`](#asyncresult) instance\nif the `transformFn` function is async.\n\n\u003e [!NOTE]\n\u003e Any exceptions that might be thrown inside the `transformFn` callback are not caught, so it is your responsibility\n\u003e to handle these exceptions. Please refer to [`Result.mapCatching()`](#mapcatchingtransformfn-transformerrorfn) for a version that catches exceptions\n\u003e and encapsulates them in a failed result.\n\n#### Example\ntransforming the value of a result\n```ts\ndeclare const result: Result\u003cnumber, Error\u003e;\n\nconst transformed = result.map((value) =\u003e value 2); // Result\u003cnumber, Error\u003e\n```\n\n#### Example\nreturning a result instance\n```ts\ndeclare const result: Result\u003cnumber, Error\u003e;\ndeclare function multiplyByTwo(value: number): Result\u003cnumber, Error\u003e;\n\nconst transformed = result.map((value) =\u003e multiplyByTwo(value)); // Result\u003cnumber, Error\u003e\n```\n\n#### Example\ndoing an async transformation\n```ts\ndeclare const result: Result\u003cnumber, Error\u003e;\n\nconst transformed = result.map(async (value) =\u003e value 2); // AsyncResult\u003cnumber, Error\u003e\n```\n\n#### Example\nreturning an async result instance\n\n```ts\ndeclare const result: Result\u003cnumber, Error\u003e;\ndeclare function storeValue(value: number): AsyncResult\u003cboolean, Error\u003e;\n\nconst transformed = result.map((value) =\u003e storeValue(value)); // AsyncResult\u003cboolean, Error\u003e\n```\n\n### mapCatching(transformFn, transformErrorFn?)\n\nLike [`Result.map`](#maptransformfn) it transforms the value of a successful result using the `transform` callback.\nIn addition, it catches any exceptions that might be thrown inside the `transform` callback and encapsulates them\nin a failed result.\n\n#### Parameters\n\n- `transformFn` callback function to transform the value of the result. The callback can be async as well.\n- `transformErrorFn` optional callback function that transforms any caught error inside `transformFn` into a specific error.\n\n**returns** * a new [`Result`](#result) instance with the transformed value, or a new [`AsyncResult`](#asyncresult) instance if the transform function is async.\n\n### mapError(transformFn)\n\nTransforms the error of a failed result using the `transform` callback into a new error.\nThis can be useful when you want to transform the error into a different error type, or when you want to provide more context to the error.\n\n#### Parameters\n\n- `transformFn` callback function to transform the error of the result.\n\n**returns** a new failed [`Result`](#result) instance with the transformed error.\n\n#### Example\n\ntransforming the error into a different error type\n\n```ts\ndeclare const result: Result\u003cnumber, Error\u003e;\n\nresult.mapError((error) =\u003e new ErrorB(error.message)); // Result\u003cnumber, ErrorB\u003e\n```\n\n### recover(onFailure)\n\nTransforms a failed result using the `onFailure` callback into a successful result. Useful for falling back to\nother scenarios when a previous operation fails.\nThe `onFailure` callback can also return other `Result` or [`AsyncResult`](#asyncresult) instances,\nwhich will be returned as-is.\nAfter a recovery, logically, the result can only be a success. Therefore, the error type is set to `never`, unless\nthe `onFailure` callback returns a result-instance with another error type.\n\n#### Parameters\n\n- `onFailure` callback function to transform the error of the result. The callback can be async as well.\n\n**returns** a new successful [`Result`](#result) instance or a new successful [`AsyncResult`](#asyncresult) instance\nwhen the result represents a failure, or the original instance if it represents a success.\n\n\u003e [!NOTE]\n\u003e Any exceptions that might be thrown inside the `onFailure` callback are not caught, so it is your responsibility\n\u003e to handle these exceptions. Please refer to [`Result.recoverCatching`](#recovercatchingonfailure) for a version that catches exceptions\n\u003e and encapsulates them in a failed result.\n\n#### Example\ntransforming the error into a value\nNote: Since we recover after trying to persist in the database, we can assume that the `DbError` has been taken care\nof and therefore it has been removed from the final result.\n```ts\ndeclare function persistInDB(item: Item): Result\u003cItem, DbError\u003e;\ndeclare function persistLocally(item: Item): Result\u003cItem, IOError\u003e;\n\npersistInDB(item).recover(() =\u003e persistLocally(item)); // Result\u003cItem, IOError\u003e\n```\n\n### recoverCatching(onFailure)\n\nLike [`Result.recover`](#recoveronfailure) it transforms a failed result using the `onFailure` callback into a successful result.\nIn addition, it catches any exceptions that might be thrown inside the `onFailure` callback and encapsulates them\nin a failed result.\n\n#### Parameters\n\n- `onFailure` callback function to transform the error of the result. The callback can be async as well.\n\n**returns** a new successful [`Result`](#result) instance or a new successful [`AsyncResult`](#asyncresult) instance when the result represents a failure, or the original instance if it represents a success.\n\n### Result.ok(value)\n\nCreates a new result instance that represents a successful outcome.\n\n#### Parameters\n\n- `value` The value to encapsulate in the result.\n\n**returns** a new [`Result`](#result) instance.\n\n#### Example\n```ts\nconst result = Result.ok(42); // Result\u003cnumber, never\u003e\n```\n\n### Result.error(error)\n\nCreates a new result instance that represents a failed outcome.\n\n#### Parameters\n\n- `error` The error to encapsulate in the result.\n\n**returns** a new [`Result`](#result) instance.\n\n#### Example\n```ts\nconst result = Result.error(new NotFoundError()); // Result\u003cnever, NotFoundError\u003e\n```\n\n### Result.isResult(possibleResult)\n\nType guard that checks whether the provided value is a [`Result`](#result) instance.\n\n#### Parameters\n\n- `possibleResult` any value that might be a [`Result`](#result) instance.\n\n**returns* `true` if the provided value is a [`Result`](#result) instance, otherwise `false`.\n\n### Result.isAsyncResult(possibleAsyncResult)\n\nType guard that checks whether the provided value is a [`AsyncResult`](#asyncresult) instance.\n\n#### Parameters\n\n- `possibleAsyncResult` any value that might be a [`AsyncResult`](#asyncresult) instance.\n\n**returns** `true` if the provided value is a [`AsyncResult`](#asyncresult) instance, otherwise `false`.\n\n### Result.all(items)\n\nSimilar to `Promise.all`, but for results.\nUseful when you want to run multiple independent operations and bundle the outcome into a single result.\nAll possible values of the individual operations are collected into an array. `Result.all` will fail eagerly,\nmeaning that as soon as any of the operations fail, the entire result will be a failure.\nEach argument can be a mixture of literal values, functions, [`Result`](#result) or [`AsyncResult`](#asyncresult) instances, or `Promise`.\n\n#### Parameters\n\n- `items` one or multiple literal value, function, [`Result`](#result) or [`AsyncResult`](#asyncresult) instance, or `Promise`.\n\n**returns** combined result of all the operations.\n\n\u003e [!NOTE]\n\u003e Any exceptions that might be thrown are not caught, so it is your responsibility\n\u003e to handle these exceptions. Please refer to [`Result.allCatching`](#resultallcatchingitems) for a version that catches exceptions\n\u003e and encapsulates them in a failed result.\n\n#### Example\nbasic usage\n```ts\ndeclare function createTask(name: string): Result\u003cTask, IOError\u003e;\n\nconst tasks = [\"task-a\", \"task-b\", \"task-c\"];\nconst result = Result.all(...tasks.map(createTask)); // Result\u003cTask[], IOError\u003e\n```\n\n#### Example\nrunning multiple operations and combining the results\n```ts\nconst result = Result.all(\n  \"a\",\n  Promise.resolve(\"b\"),\n  Result.ok(\"c\"),\n  Result.try(async () =\u003e \"d\"),\n  () =\u003e \"e\",\n  () =\u003e Result.try(async () =\u003e \"f\"),\n  () =\u003e Result.ok(\"g\"),\n  async () =\u003e \"h\",\n); // AsyncResult\u003c[string, string, string, string, string, string, string, string], Error\u003e\n```\n\n### Result.allCatching(items)\n\nSimilar to [`Result.all`](#resultallitems), but catches any exceptions that might be thrown during the operations.\n\n#### Parameters\n\n- `items` one or multiple literal value, function, [`Result`](#result) or [`AsyncResult`](#asyncresult) instance, or `Promise`.\n\n**returns** combined result of all the operations.\n\n### Result.wrap(fn)\n\nWraps a function and returns a new function that returns a result. Especially useful when you want to work with\nexternal functions that might throw exceptions.\nThe returned function will catch any exceptions that might be thrown and encapsulate them in a failed result.\n\n#### Parameters\n\n- `fn` function to wrap. Can be synchronous or asynchronous.\n\n**returns** a new function that returns a result.\n\n#### Example\nbasic usage\n```ts\ndeclare function divide(a: number, b: number): number;\n\nconst safeDivide = Result.wrap(divide);\nconst result = safeDivide(10, 0); // Result\u003cnumber, Error\u003e\n```\n\n### Result.try(fn, [transform])\n\nExecutes the given `fn` function and encapsulates the returned value as a successful result, or the\nthrown exception as a failed result. In a way, you can view this method as a try-catch block that returns a result.\n\n#### Parameters\n\n- `fn` function with code to execute. Can be synchronous or asynchronous.\n- `transform` optional callback to transform the caught error into a more meaningful error.\n\n**returns** a new [`Result`](#result) instance.\n\n#### Example\nbasic usage\n```ts\ndeclare function saveFileToDisk(filename: string): void; // might throw an error\n\nconst result = Result.try(() =\u003e saveFileToDisk(\"file.txt\")); // Result\u003cvoid, Error\u003e\n```\n\n#### Example\nbasic usage with error transformation\n```ts\ndeclare function saveFileToDisk(filename: string): void; // might throw an error\n\nconst result = Result.try(\n  () =\u003e saveFileToDisk(\"file.txt\"),\n  (error) =\u003e new IOError(\"Failed to save file\", { cause: error })\n); // Result\u003cvoid, IOError\u003e\n```\n\n### Result.fromAsync(promise)\n\nUtility method to transform a Promise, that holds a literal value or\na [`Result`](#result) or [`AsyncResult`](#asyncresult) instance, into an [`AsyncResult`](#asyncresult) instance. Useful when you want to immediately chain operations\nafter calling an async function.\n\n#### Parameters\n\n- `promise` a Promise that holds a literal value or a [`Result`](#result) or [`AsyncResult`](#asyncresult) instance.\n\n**returns** a new [`AsyncResult`](#asyncresult) instance.\n\n\u003e [!NOTE]\n\u003e Any exceptions that might be thrown are not caught, so it is your responsibility\n\u003e to handle these exceptions. Please refer to [`Result.fromAsyncCatching`](#resultfromasynccatchingpromise) for a version that catches exceptions\n\u003e and encapsulates them in a failed result.\n\n#### Example\nbasic usage\n\n```ts\ndeclare function someAsyncOperation(): Promise\u003cResult\u003cnumber, Error\u003e\u003e;\n\n// without 'Result.fromAsync'\nconst result = (await someAsyncOperation()).map((value) =\u003e value 2); // Result\u003cnumber, Error\u003e\n\n// with 'Result.fromAsync'\nconst asyncResult = Result.fromAsync(someAsyncOperation()).map((value) =\u003e value 2); // AsyncResult\u003cnumber, Error\u003e\n```\n\n### Result.fromAsyncCatching(promise)\n\nSimilar to [`Result.fromAsync`](#resultfromasyncpromise) this method transforms a Promise into an [`AsyncResult`](#asyncresult) instance.\nIn addition, it catches any exceptions that might be thrown during the operation and encapsulates them in a failed result.\n\n### Result.assertOk(result)\n\nAsserts that the provided result is successful. If the result is a failure, an error is thrown.\nUseful in unit tests.\n\n#### Parameters\n\n- `result` the result instance to assert against.\n\n### Result.assertError(result)\n\nAsserts that the provided result is a failure. If the result is successful, an error is thrown.\nUseful in unit tests.\n\n#### Parameters\n\n- `result` the result instance to assert against.\n\n## AsyncResult\n\nRepresents the asynchronous outcome of an operation that can either succeed or fail.\n\n```ts\nclass AsyncResult\u003cValue, Error\u003e {}\n```\n\n### isAsyncResult\n\nUtility getter that checks if the current instance is an `AsyncResult`.\n\n### toTuple()\n\n**returns** the result in a tuple format where the first element is the value and the second element is the error.\n\nIf the result is successful, the error will be `null`. If the result is a failure, the value will be `null`.\nThis method is especially useful when you want to destructure the result into a tuple and use TypeScript's narrowing capabilities.\n\n#### Example\nNarrowing down the type using destructuring\n```ts\ndeclare const result: AsyncResult\u003cnumber, ErrorA\u003e;\n\nconst [value, error] = result.toTuple();\n\nif (error) {\n  // error is ErrorA\n} else {\n  // at this point the value must be a number\n}\n```\n\n### errorOrNull()\n\n**returns** the encapsulated error if the result is a failure, otherwise `null`.\n\n### getOrNull()\n\n**returns** the encapsulated value if the result is successful, otherwise `null`.\n\n### getOrDefault(defaultValue)\n\nRetrieves the encapsulated value of the result, or a default value if the result is a failure.\n\n#### Parameters\n\n- `defaultValue` The value to return if the result is a failure.\n\n**returns** The encapsulated value if the result is successful, otherwise the default value.\n\n#### Example\nobtaining the value of a result, or a default value\n```ts\ndeclare const result: AsyncResult\u003cnumber, Error\u003e;\n\nconst value = await result.getOrDefault(0); // number\n```\n\n#### Example\nusing a different type for the default value\n```ts\ndeclare const result: AsyncResult\u003cnumber, Error\u003e;\n\nconst value = await result.getOrDefault(\"default\"); // number | string\n```\n\n### getOrElse(onFailure)\n\nRetrieves the value of the result, or transforms the error using the `onFailure` callback into a value.\n\n#### Parameters\n\n- `onFailure` callback function which allows you to transform the error into a value. The callback can be async as well.\n\n**returns** either the value if the result is successful, or the transformed error.\n\n#### Example\ntransforming the error into a value\n```ts\ndeclare const result: AsyncResult\u003cnumber, Error\u003e;\n\nconst value = await result.getOrElse((error) =\u003e 0); // number\n```\n\n#### Example\nusing an async callback\n```ts\nconst value = await result.getOrElse(async (error) =\u003e 0); // number\n```\n\n### getOrThrow()\n\nRetrieves the encapsulated value of the result, or throws an error if the result is a failure.\n\n**returns** The encapsulated value if the result is successful.\n\n**throws** the encapsulated error if the result is a failure.\n\n#### Example\nobtaining the value of a result, or throwing an error\n```ts\ndeclare const result: AsyncResult\u003cnumber, Error\u003e;\n\nconst value = await result.getOrThrow(); // number\n```\n\n### fold(onSuccess, onFailure)\n\nReturns the result of the `onSuccess` callback when the result represents success or\nthe result of the `onFailure` callback when the result represents a failure.\n\n\u003e [!NOTE]\n\u003e Any exceptions that might be thrown inside the callbacks are not caught, so it is your responsibility\n\u003e to handle these exceptions\n\n#### Parameters\n\n- `onSuccess` callback function to run when the result is successful. The callback can be async as well.\n\n- `onFailure` callback function to run when the result is a failure. The callback can be async as well.\n\n**returns** the result of the callback that was executed.\n\n#### Example\nfolding a result to a response-like object\n\n```ts\ndeclare const result: AsyncResult\u003cUser, NotFoundError | UserDeactivatedError\u003e;\n\nconst response = await result.fold(\n  (user) =\u003e ({ status: 200, body: user }),\n  (error) =\u003e {\n    switch (error.type) {\n      case \"not-found\":\n        return { status: 404, body: \"User not found\" };\n      case \"user-deactivated\":\n        return { status: 403, body: \"User is deactivated\" };\n    }\n  }\n);\n```\n\n### onFailure(action)\n\nCalls the `action` callback when the result represents a failure. It is meant to be used for\nside-effects and the operation does not modify the result itself.\n\n#### Parameters\n\n- `action` callback function to run when the result is a failure. The callback can be async as well.\n\n**returns** the original instance of the result.\n\n\u003e [!NOTE]\n\u003e Any exceptions that might be thrown inside the `action` callback are not caught, so it is your responsibility\n\u003e to handle these exceptions\n\n#### Example\nadding logging between operations\n```ts\ndeclare const result: AsyncResult\u003cnumber, Error\u003e;\n\nresult\n  .onFailure((error) =\u003e console.error(\"I'm failing!\", error))\n  .map((value) =\u003e value 2); // proceed with other operations\n```\n\n### onSuccess(action)\n\nCalls the `action` callback when the result represents a success. It is meant to be used for\nside-effects and the operation does not modify the result itself.\n\n#### Parameters\n\n- `action` callback function to run when the result is successful. The callback can be async as well.\n\n**returns** the original instance of the result.\n\n\u003e [!NOTE]\n\u003e Any exceptions that might be thrown inside the `action` callback are not caught, so it is your responsibility\n\u003e to handle these exceptions\n\n#### Example\nadding logging between operations\n```ts\ndeclare const result: AsyncResult\u003cnumber, Error\u003e;\n\nresult\n  .onSuccess((value) =\u003e console.log(\"I'm a success!\", value))\n  .map((value) =\u003e value 2); // proceed with other operations\n```\n\n#### Example\nusing an async callback\n```ts\ndeclare const result: AsyncResultResult\u003cnumber, Error\u003e;\n\nconst asyncResult = await result.onSuccess(async (value) =\u003e someAsyncOperation(value));\n```\n\n### map(transformFn)\n\nTransforms the value of a successful result using the `transform` callback.\nThe `transform` callback can also return other `Result` or [`AsyncResult`](#asyncresult) instances,\nwhich will be returned as-is (the `Error` types will be merged).\nThe operation will be ignored if the result represents a failure.\n\n#### Parameters\n\n- `transformFn` callback function to transform the value of the result. The callback can be async as well.\n\n**returns** a new [`AsyncResult`](#asyncresult) instance with the transformed value\n\n\u003e [!NOTE]\n\u003e Any exceptions that might be thrown inside the `transform` callback are not caught, so it is your responsibility\n\u003e to handle these exceptions. Please refer to [`AsyncResult.mapCatching`](#mapcatchingtransformfn-transformerrorfn-1) for a version that catches exceptions\n\u003e and encapsulates them in a failed result.\n\n#### Example\ntransforming the value of a result\n```ts\ndeclare const result: AsyncResult\u003cnumber, Error\u003e;\n\nconst transformed = result.map((value) =\u003e value 2); // AsyncResult\u003cnumber, Error\u003e\n```\n\n#### Example\nreturning a result instance\n```ts\ndeclare const result: AsyncResult\u003cnumber, Error\u003e;\ndeclare function multiplyByTwo(value: number): Result\u003cnumber, Error\u003e;\n\nconst transformed = result.map((value) =\u003e multiplyByTwo(value)); // AsyncResult\u003cnumber, Error\u003e\n```\n\n#### Example\ndoing an async transformation\n```ts\ndeclare const result: AsyncResult\u003cnumber, Error\u003e;\n\nconst transformed = result.map(async (value) =\u003e value 2); // AsyncResult\u003cnumber, Error\u003e\n```\n\n#### Example\nreturning an async result instance\n\n```ts\ndeclare const result: AsyncResult\u003cnumber, Error\u003e;\ndeclare function storeValue(value: number): AsyncResult\u003cboolean, Error\u003e;\n\nconst transformed = result.map((value) =\u003e storeValue(value)); // AsyncResult\u003cboolean, Error\u003e\n```\n\n### mapCatching(transformFn, transformErrorFn?)\n\nLike [`AsyncResult.map`](#maptransformfn-1) it transforms the value of a successful result using the `transformFn` callback.\nIn addition, it catches any exceptions that might be thrown inside the `transformFn` callback and encapsulates them\nin a failed result.\n\n#### Parameters\n\n- `transformFn` callback function to transform the value of the result. The callback can be async as well.\n- `transformErrorFn` optional callback function that transforms any caught error inside `transformFn` into a specific error.\n\n**returns** a new [`AsyncResult`](#asyncresult) instance with the transformed value\n\n### mapError(transformFn)\n\nTransforms the error of a failed result using the `transform` callback into a new error.\nThis can be useful when you want to transform the error into a different error type, or when you want to provide more context to the error.\n\n#### Parameters\n\n- `transformFn` callback function to transform the error of the result.\n\n**returns** a new failed [`AsyncResult`](#asyncresult) instance with the transformed error.\n\n#### Example\n\ntransforming the error into a different error type\n\n```ts\nconst result = Result.try(() =\u003e fetch(\"https://example.com\"))\n  .mapCatching((response) =\u003e response.json() as Promise\u003cData\u003e)\n  .mapError((error) =\u003e new FetchDataError(\"Failed to fetch data\", { cause: error }));\n  // AsyncResult\u003cData, FetchDataError\u003e;\n```\n\n\n### recover(onFailure)\n\nTransforms a failed result using the `onFailure` callback into a successful result. Useful for falling back to\nother scenarios when a previous operation fails.\nThe `onFailure` callback can also return other `Result` or [`AsyncResult`](#asyncresult) instances,\nwhich will be returned as-is.\nAfter a recovery, logically, the result can only be a success. Therefore, the error type is set to `never`, unless\nthe `onFailure` callback returns a result-instance with another error type.\n\n#### Parameters\n\n- `onFailure` callback function to transform the error of the result. The callback can be async as well.\n\n**returns** a new successful [`AsyncResult`](#asyncresult) instance when the result represents a failure, or the original instance\nif it represents a success.\n\n\u003e [!NOTE]\n\u003e Any exceptions that might be thrown inside the `onFailure` callback are not caught, so it is your responsibility\n\u003e to handle these exceptions. Please refer to [`AsyncResult.recoverCatching`](#recovercatchingonfailure-1) for a version that catches exceptions\n\u003e and encapsulates them in a failed result.\n\n#### Example\ntransforming the error into a value\nNote: Since we recover after trying to persist in the database, we can assume that the `DbError` has been taken care\nof and therefore it has been removed from the final result.\n```ts\ndeclare function persistInDB(item: Item): AsyncResult\u003cItem, DbError\u003e;\ndeclare function persistLocally(item: Item): AsyncResult\u003cItem, IOError\u003e;\n\npersistInDB(item).recover(() =\u003e persistLocally(item)); // AsyncResult\u003cItem, IOError\u003e\n```\n\n### recoverCatching(onFailure)\n\nLike [`AsyncResult.recover`](#recoveronfailure-1) it transforms a failed result using the `onFailure` callback into a successful result.\nIn addition, it catches any exceptions that might be thrown inside the `onFailure` callback and encapsulates them\nin a failed result.\n\n#### Parameters\n\n- `onFailure` callback function to transform the error of the result. The callback can be async as well.\n\n**returns** a new successful [`AsyncResult`](#asyncresult) instance when the result represents a failure, or the original instance\nif it represents a success.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feverweij%2Ftypescript-result","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feverweij%2Ftypescript-result","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feverweij%2Ftypescript-result/lists"}