{"id":13495007,"url":"https://github.com/inato/fp-ts-cheatsheet","last_synced_at":"2025-03-28T15:32:34.200Z","repository":{"id":40123238,"uuid":"278371835","full_name":"inato/fp-ts-cheatsheet","owner":"inato","description":"FP-TS Cheat Sheet","archived":false,"fork":false,"pushed_at":"2023-12-15T08:26:17.000Z","size":64,"stargazers_count":418,"open_issues_count":2,"forks_count":31,"subscribers_count":22,"default_branch":"main","last_synced_at":"2024-08-01T19:53:31.117Z","etag":null,"topics":["fp-ts","functional-programming","immutable","monads","typescript"],"latest_commit_sha":null,"homepage":"https://inato.github.io/fp-ts-cheatsheet/","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/inato.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2020-07-09T13:26:22.000Z","updated_at":"2024-07-28T00:01:14.000Z","dependencies_parsed_at":"2024-01-06T02:03:50.914Z","dependency_job_id":"eb01c321-10ac-4296-9328-34403291cc8e","html_url":"https://github.com/inato/fp-ts-cheatsheet","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/inato%2Ffp-ts-cheatsheet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inato%2Ffp-ts-cheatsheet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inato%2Ffp-ts-cheatsheet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inato%2Ffp-ts-cheatsheet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/inato","download_url":"https://codeload.github.com/inato/fp-ts-cheatsheet/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":222389518,"owners_count":16976487,"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-ts","functional-programming","immutable","monads","typescript"],"created_at":"2024-07-31T19:01:30.295Z","updated_at":"2024-10-31T09:31:42.886Z","avatar_url":"https://github.com/inato.png","language":null,"funding_links":[],"categories":["Others"],"sub_categories":[],"readme":"# :memo: `fp-ts` cheatsheet\n\nMore detailed explanations can be found in the [Details](Details.md) document.\n\n1. [Imports](#imports)\n2. [Pipe and Flow](#pipe-flow)\n3. [Option](#option)\n4. [Either](#either)\n5. [TaskEither](#taskeither)\n6. [Array and ReadonlyArray](#array)\n7. [Do-notation](#do-notation)\n\n## \u003ca name=\"imports\"\u003e\u003c/a\u003eImports\n\n```ts\nimport { either, option } from 'fp-ts'; // import modules from root\nimport { flow, pipe } from 'fp-ts/functions'; // import functions from functions\nimport { Either } from 'fp-ts/Either'; // import types from their module\n\n// rename common long module names\nimport { readerTaskEither as rte } from 'fp-ts';\n```\n\n## \u003ca name=\"pipe-flow\"\u003e\u003c/a\u003ePipe and Flow\n\n```ts\nconst value = 'value';\n\n// Imperative style\nconst value1 = addSthg(value);\nconst value2 = doSthgElse(value1);\nconst finalValue = doFinalSthg(value2);\n// Or maybe inline\nconst finalValue = doFinalSthg(doSthgElse(addSthg(value)));\n\n// With pipe\nconst finalValue = pipe(value, addSthg, doSthgElse, doFinalSthg);\n\n// With flow\nconst transformations = flow(addSthg, doSthgElse, doFinalSthg);\nconst finalValue = transformations(value);\n```\n\n## \u003ca name=\"option\"\u003e\u003c/a\u003eOption\n\n### \u003ca name=\"option-builders\"\u003e\u003c/a\u003eCreate an `Option\u003cT\u003e`\n\n```ts\n// Build an Option\noption.none;\noption.some('value');\n\n// Build from a value\noption.fromNullable(null); // =\u003e option.none\noption.fromNullable('value'); // =\u003e option.some('value')\n\n// Build from a predicate\nconst isEven = number =\u003e number % 2 === 0;\n\noption.fromPredicate(isEven)(3); // =\u003e option.none\noption.fromPredicate(isEven)(4); // =\u003e option.some(4)\n\n// Convert from another type (eg. Either)\nconst leftEither = either.left('whatever');\nconst rightEither = either.right('value');\n\noption.fromEither(leftEither); // =\u003e option.none\noption.fromEither(rightEither); // =\u003e option.some('value')\n```\n\n#### \u003ca name=\"option-getters\"\u003e\u003c/a\u003eExtract inner value\n\n```ts\nconst noneValue = option.none;\nconst someValue = option.of(42);\n\n// Convert Option\u003cT\u003e to T | undefined\noption.toUndefined(noneValue); // =\u003e undefined\noption.toUndefined(someValue); // =\u003e 42\n\n// Convert Option\u003cT\u003e to T | null\noption.toNullable(noneValue); // =\u003e null\noption.toNullable(someValue); // =\u003e 42\n\n// Convert Option\u003cT\u003e with a default value\noption.getOrElse(() =\u003e 0)(noneValue); // =\u003e 0\noption.getOrElse(() =\u003e 0)(someValue); // =\u003e 42\n\n// Convert Option\u003cT\u003e to T | U with a default value of type U\noption.getOrElseW(() =\u003e 'default')(noneValue); // =\u003e 'default': number | string\n\n// Apply a different function on None/Some(...)\nconst doubleOrZero = option.match(\n  () =\u003e 0, // none case\n  (n: number) =\u003e 2 * n // some case\n);\n\ndoubleOrZero(noneValue); // =\u003e 0\ndoubleOrZero(someValue); // =\u003e 84\n\n// Pro-tip: option.match is short for the following:\nconst doubleOfZeroBis = flow(\n  option.map((n: number) =\u003e 2 * n), // some case\n  option.getOrElse(() =\u003e 0) // none case\n);\n```\n\n## \u003ca name=\"either\"\u003e\u003c/a\u003eEither\n\n### \u003ca name=\"either-builders\"\u003e\u003c/a\u003eCreate an `Either\u003cE, A\u003e`\n\n```ts\n// Build an Either\nconst leftValue = either.left('value');\nconst rightValue = either.right('value');\n\n// Build from a value\neither.fromNullable('value was nullish')(null); // =\u003e either.left('value was nullish')\neither.fromNullable('value was nullish')('value'); // =\u003e either.right('value')\n\n// Build from a predicate\nconst isEven = (num: number) =\u003e num % 2 === 0;\n\nconst eitherBuilder = either.fromPredicate(\n  isEven,\n  number =\u003e `${number} is an odd number`\n);\n\neitherBuilder(3); // =\u003e either.left('3 is an odd number')\neitherBuilder(4); // =\u003e either.right(4)\n\n// Convert from another type (eg. Option)\nconst noneValue = option.none;\nconst someValue = option.some('value');\n\neither.fromOption(() =\u003e 'value was nullish')(noneValue); // =\u003e either.left('value was nullish')\neither.fromOption(() =\u003e 'value was nullish')(someValue); // =\u003e either.right('value')\n```\n\n### \u003ca name=\"either-getters\"\u003e\u003c/a\u003eExtract inner value\n\n```ts\nconst leftValue = either.left(\"Division by Zero!\");\nconst rightValue = either.right(10);\n\n// Convert Either\u003cE, A\u003e to A with a default value\neither.getOrElse(() =\u003e 0)(leftValue); // =\u003e 0\neither.getOrElse(() =\u003e 0)(rightValue); // =\u003e 10\n\n// Apply a different function on Left(...)/Right(...)\nconst doubleOrZero = either.match(\n  (error: string) =\u003e {\n    console.log(`The error was ${error}`);\n    return 0;\n  },\n  (n: number) =\u003e 2 * n,\n);\n\ndoubleOrZero(leftValue); // =\u003e 0 - also logs \"The error was Division by Zero!\"\ndoubleOrZero(rightValue); // =\u003e 20\n\n// Pro-tip: either.match is short for the following:\nconst doubleOrZeroBis = flow(\n  either.map((n: number) =\u003e 2 * n),\n  either.getOrElse((error: string) =\u003e {\n    console.log(`The error was ${error}`);\n    return 0;\n  });\n);\n```\n\n## \u003ca name=\"taskeither\"\u003e\u003c/a\u003eTaskEither\n\n### \u003ca name=\"taskeither-builders\"\u003e\u003c/a\u003eCreate a `TaskEither\u003cE, A\u003e`\n\n```ts\n// Build a TaskEither\nconst leftValue = taskEither.left('value');\nconst rightValue = taskEither.right('value');\n\n// The taskEither module also provides similar builder functions\n// to either, namely: `fromNullable`, `fromOption`, `fromPredicate`...\n\n// Convert from Either\nconst eitherValue = either.right(42);\n\ntaskEither.fromEither(eitherValue); // =\u003e taskEither.right(42)\n\n// Build from an async function\nconst asyncIsEven = async (n: number) =\u003e {\n  if (!isEven(n)) {\n    throw new Error(`${n} is odd`);\n  }\n\n  return n;\n};\n\nconst buildTaskEither = (n: number) =\u003e\n  taskEither.tryCatch(\n    () =\u003e asyncIsEven(n),\n    (error: Error) =\u003e error.message\n  );\n\nbuildTaskEither(3); // =\u003e taskEither.left('3 is odd')\nbuildTaskEither(4); // =\u003e taskEither.right(4)\n```\n\n#### \u003ca name=\"taskeither-getters\"\u003e\u003c/a\u003eExtract inner value\n\n```ts\n// Simple case: an infaillible Task\nconst someTask = task.of(42);\n\n// Invoking a Task returns the underlying Promise\nawait someTask(); // =\u003e 42\n\n// TaskEither\nconst someTaskEither = taskEither.right(42);\nconst eitherValue = await someTaskEither(); // =\u003e either.right(42)\neither.getOrElse(() =\u003e 0)(eitherValue); // =\u003e 42\n\n// Or more directly\nconst infaillibleTask = taskEither.getOrElse(() =\u003e 0)(someTaskEither); // =\u003e task.of(42)\nawait infaillibleTask(); // =\u003e 42\n```\n\n## \u003ca name=\"array\"\u003e\u003c/a\u003eReadonlyArray\n\n### \u003ca name=\"basic-manipulation\"\u003e\u003c/a\u003eBasic manipulation\n\n```ts\nconst someArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];\n\n// filter and map\nconst result = pipe(\n  someArray,\n  readonlyArray.filter(isEven),\n  readonlyArray.map(square)\n); // =\u003e [0, 4, 16, 36, 64]\n\n// or in one go with filterMap\nconst result = pipe(\n  someArray,\n  readonlyArray.filterMap(\n    flow(option.fromPredicate(isEven), option.map(square))\n  )\n);\n```\n\n### \u003ca name=\"ord\"\u003e\u003c/a\u003eSort elements with Ord\n\n```ts\nconst strings = ['zyx', 'abc', 'klm'];\n\n// basic sort\nconst sortedStrings = pipe(strings, readonlyArray.sort(string.Ord)); // =\u003e ['abc', 'klm', 'zyx']\n\n// reverse sort\nconst reverseSortedStrings = pipe(\n  strings,\n  readonlyArray.sort(ord.reverse(string.Ord))\n); // =\u003e ['zyx', 'klm', 'abc']\n\n// sort Option\nconst optionalNumbers = [option.some(1337), option.none, option.some(42)];\n\nconst sortedNums = pipe(nums, readonlyArray.sort(option.getOrd(number.Ord))); // =\u003e [option.none, option.some(42), option.some(1337)]\n\n// sort complex objects with different rules\ntype User = {\n  name: string;\n  age: Option\u003cnumber\u003e;\n};\n\nconst byName = pipe(\n  string.Ord,\n  ord.contramap((user: User) =\u003e user.name)\n);\n\nconst byAge = pipe(\n  option.getOrd(number.Ord),\n  ord.contramap((user: User) =\u003e user.age)\n);\n\nconst sortUsers = readonlyArray.sortBy([byAge, byName]); // will sort an array of users by age first, then by name\n```\n\n## \u003ca name=\"do-notation\"\u003e\u003c/a\u003eDo-notation\n\n```ts\nimport { readerTaskEither as rte } from 'fp-ts';\nimport { pipe } from 'fp-ts/function';\nimport { ReaderTaskEither } from 'fp-ts/ReaderTaskEither';\n\ndeclare const foo: ReaderTaskEither\u003cR1, E1, A1\u003e;\ndeclare const bar: ReaderTaskEither\u003cR2, E2, A2\u003e;\ndeclare const baz: (props: {\n  foo: A1;\n  bar: A2;\n}) =\u003e ReaderTaskEither\u003cR3, E3, A3\u003e;\ndeclare const quux: (props: {\n  foo: A1;\n  bar: A2;\n  baz: A3;\n}) =\u003e ReaderTask\u003cR4, A4\u003e;\ndeclare const transform: (props: { foo: A1; bar: A2; baz: A3 }) =\u003e B;\n\npipe(\n  rte.Do,\n  rte.apS('foo', foo),\n  rte.apSW('bar', bar),\n  rte.bindW('baz', baz),\n  rte.chainFirstReaderTaskKW(quux),\n  rte.map(transform)\n);\n// =\u003e ReaderTaskEither\u003c\n//      R1 \u0026 R2 \u0026 R3 \u0026 R4,\n//      E1 | E2 | E3,\n//      B,\n//    \u003e\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finato%2Ffp-ts-cheatsheet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Finato%2Ffp-ts-cheatsheet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finato%2Ffp-ts-cheatsheet/lists"}