{"id":25683334,"url":"https://github.com/mikechabot/maybe-baby","last_synced_at":"2025-06-25T18:09:50.502Z","repository":{"id":14695030,"uuid":"76878718","full_name":"mikechabot/maybe-baby","owner":"mikechabot","description":"Minimize defensive coding. A JavaScript implementation of the Maybe monad.","archived":false,"fork":false,"pushed_at":"2023-01-06T01:33:44.000Z","size":2319,"stargazers_count":42,"open_issues_count":12,"forks_count":3,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-05-25T10:09:02.640Z","etag":null,"topics":["javascript","monad"],"latest_commit_sha":null,"homepage":"https://mikechabot.github.io/maybe-baby/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mikechabot.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}},"created_at":"2016-12-19T16:35:03.000Z","updated_at":"2021-12-28T05:05:51.000Z","dependencies_parsed_at":"2023-01-13T18:04:16.796Z","dependency_job_id":null,"html_url":"https://github.com/mikechabot/maybe-baby","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mikechabot/maybe-baby","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikechabot%2Fmaybe-baby","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikechabot%2Fmaybe-baby/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikechabot%2Fmaybe-baby/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikechabot%2Fmaybe-baby/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mikechabot","download_url":"https://codeload.github.com/mikechabot/maybe-baby/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikechabot%2Fmaybe-baby/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261927619,"owners_count":23231380,"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","monad"],"created_at":"2025-02-24T16:51:23.057Z","updated_at":"2025-06-25T18:09:50.474Z","avatar_url":"https://github.com/mikechabot.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# maybe-baby\n\n\u003e 2.x will be maintained, however, if possible for your repository, you should opt to use TypeScript's [optional chaining](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html), which was introduced in 3.7\n\n\u003cdiv align=\"center\"\u003e\nMinimize defensive coding. A JavaScript implementation of the \u003ca href=\"https://en.wikipedia.org/wiki/Monad_(functional_programming)#The_Maybe_monad\"\u003eMaybe monad\u003c/a\u003e.\n\u003cbr /\u003e\u003cbr /\u003e\n  \u003ca href=\"https://www.npmjs.com/package/maybe-baby\"\u003e\n    \u003cimg src=\"https://img.shields.io/npm/v/maybe-baby.svg?style=flat-square\" alt=\"npm version\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://travis-ci.org/mikechabot/maybe-baby\"\u003e\n    \u003cimg src=\"https://travis-ci.org/mikechabot/maybe-baby.svg?branch=master\" alt=\"build status\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://coveralls.io/github/mikechabot/maybe-baby?branch=master\"\u003e\n    \u003cimg src=\"https://coveralls.io/repos/github/mikechabot/maybe-baby/badge.svg?branch=master\u0026cacheBuster=1\" alt=\"coverage status\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://david-dm.org/mikechabot/maybe-baby\"\u003e\n    \u003cimg src=\"https://david-dm.org/mikechabot/maybe-baby.svg\" alt=\"dependency status\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://david-dm.org/mikechabot/maybe-baby?type=dev\"\u003e\n    \u003cimg src=\"https://david-dm.org/mikechabot/maybe-baby/dev-status.svg\" alt=\"devDependency status\" /\u003e\n  \u003c/a\u003e\n\u003c/div\u003e\n\n\u003chr /\u003e\n\n- [Install](#install)\n- [Getting Started](#getting-started)\n- [Docs](#docs)\n- [Migration](#migration)\n- [API](#api)\n  - [of](#of)\n  - [isJust](#isjust)\n  - [isNothing](#isnothing)\n  - [join](#join)\n  - [orElse](#orelse)\n  - [map](#mapfunc)\n  - [chain](#chainfunc)\n- [Credit](#credit)\n\n## \u003ca id=\"install\"\u003eInstall\u003c/a\u003e\n\n* `npm install --save maybe-baby`\n* `yarn add maybe-baby`\n\n---\n\n## \u003ca id=\"getting-started\"\u003eGetting Started\u003c/a\u003e\n\nWhat if we need the `zipCode` of the user below, which lives on the `address` object? \n\n```javascript\nconst user = { \n  email: 'foo@bar.com',\n  address: null,\n  name: {\n     first: 'John',\n     last: null,\n     middle: null\n  }\n};\n```\n\nAccessing it via dot notation will result in an error: \n\n```javascript\nconst zipCode = user.address.zipCode;  // Uncaught TypeError: Cannot read property 'zipCode' of undefined\n```\n\n### Possible Solutions?\n\n1. Write some ugly null checks that don't scale well:\n\n```javascript\nconst getZipCode = (user) =\u003e {\n  if (user !== null \u0026\u0026 user !== undefined) {\n    if (user.address !== null \u0026\u0026 user.address !== undefined) {\n      return user.address.zipCode\n    }\n  }\n}\n```\n\n2. Use [`_.get()`](https://lodash.com/docs/4.17.4#get) or something similar, but these libraries have large footprints, and most likely won't be implementing the monadic structure.\n\n3. Wait for [optional chaining](https://github.com/tc39/proposal-optional-chaining) to be approved in ECMA, or use [babel-plugin-transform-optional-chaining](https://www.npmjs.com/package/babel-plugin-transform-optional-chaining).\n\n4. Use TypeScript's [optional chaining](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html) \n\n### A Better Solution?\n\n1. Use `maybe-baby` to minimize defensive coding:\n\n```javascript\nimport Maybe from 'maybe-baby';\n\n// Use a function getter\nconst getZipCode = (user) =\u003e Maybe.of(() =\u003e user.address.zipCode).join();\n\n```\n\nNow we can safely get the `zipCode` without worrying about the shape of the object, or encountering `TypeErrors`:\n\n```js\nconst zipCode = getZipCode(user);\nconsole.log(zipCode);  // undefined\n```\n\n----\n\n## \u003ca id=\"docs\"\u003eDocs\u003c/a\u003e\n\nDocumentation generated via [JSDoc](https://github.com/jsdoc3/jsdoc).\n\n* [https://mikechabot.github.io/maybe-baby/](https://mikechabot.github.io/maybe-baby/)\n\n---\n\n## \u003ca id=\"migration\"\u003eMigrating from 1.x to 2.x\u003c/a\u003e\n\nBreaking changes were introduced in 2.0.0; the following redundant function were removed.\n\n\u003e Maybe.of(\u003cfunc\u003e) can replicate the behavior of `prop`, `props`, and `path`.\n\n### `prop(val: string | number)`\n\n```javascript\nconst obj = Maybe.of({ \n  foo: { \n    bar: [123, 456] \n  } \n});\n\n// Incorrect\nconst bar = obj.prop(\"foo\").join(); // { bar: [123, 456] }\n\n// Correct\nMaybe.of(() =\u003e obj.join().foo).join(); // { bar: [123, 456] }\n\n// Incorrect\nobj\n  .prop(\"foo\")\n  .prop(\"bar\")\n  .prop(1)\n  .join(); // 456\n\n// Correct\nMaybe.of(() =\u003e obj.join().foo.bar[1]).join() // 456\n```\n\n### `props(...args)`\n\n```javascript\nconst obj = Maybe.of({\n  foo: 'bar',\n  baz: [1,2,3]\n});\n\n// Incorrect\nobj.props('baz', 0).join(); // 1\n\n// Correct\nMaybe.of(() =\u003e obj.join().baz[0]).join(); // 1\n```\n\n### `props(val: string)`\n\n```javascript\nconst obj = Maybe.of({\n  foo: 'bar',\n  baz: [1,2,3]\n});\n\n// Incorrect\nobj.path('baz.0').join() // 1\n\n// Correct\nMaybe.of(() =\u003e obj.join().baz[0]).join(); // 1\n```\n\n---\n\n## \u003ca id=\"api\"\u003eAPI\u003c/a\u003e\n\nCheck out the API below, or the complete [documentation](https://mikechabot.github.io/maybe-baby/).\n\n### \u003ca id=\"of\"\u003e`of(val: unknown | OfTypeFunc\u003cT\u003e)`\u003c/a\u003e\n\nAccepts a value of any type, and returns a monad:\n\n```javascript\nconst str = Maybe.of('foo');\nconst num = Maybe.of(123);\nconst bool = Maybe.of(true);\nconst obj = Maybe.of({});\nconst arr = Maybe.of([]);\nconst empty = Maybe.of(null);\nconst undef = Maybe.of(undefined);\n```\n\nAccepts a function, and sets the function's return value as the monad's value, returns a monad. \n\n\u003e If the function results in an error, the monad's value is set to `undefined`.\n\n```typescript\ntype OfTypeFunc\u003cT\u003e = () =\u003e T;\n\nconst user = {};\nconst mZipCode = Maybe.of(() =\u003e user.address.zipCode);\n\nconsole.log(mZipCode.join()); // undefined\n```\n----\n\n### \u003ca id=\"isjust\"\u003e`isJust(): boolean`\u003c/a\u003e\n\nReturns `true` if the value is not `null` or `undefined`:\n\n```javascript\nMaybe.of(123).isJust();   // true\nMaybe.of(null).isJust();  // false\n```\n\n----\n\n### \u003ca id=\"isnothing\"\u003e`isNothing(): boolean`\u003c/a\u003e\n\nReturns `true` if the value is `null` or `undefined`:\n\n```javascript\nMaybe.of(123).isNothing();   // false\nMaybe.of(null).isNothing();  // true\n```\n----\n\n### \u003ca id=\"join\"\u003e`join(): T`\u003c/a\u003e\n\nReturns the value:\n\n```javascript\nMaybe.of(123).join();   // 123\nMaybe.of(null).join();  // null\n```\n\n----\n\n### \u003ca id=\"orelse\"\u003e`orElse(defaultValue: unknown): Maybe`\u003c/a\u003e\n\nChain to the end of a monad to return as the default value if `isNothing()` is `true`:\n\n```javascript\nMaybe.of(undefined)\n  .orElse('No Value')\n  .join();  // 'No Value'\n```\n\n----\n\n### \u003ca id=\"mapfunc\"\u003e`map(transform: (val: T) =\u003e T | Maybe\u003cT\u003e): Maybe`\u003c/a\u003e\n\nApply a transformation to the monad, and return a new monad:\n\n```javascript\nconst val = 1;\nconst newVal = Maybe.of(val).map(val =\u003e val + 1);\n\nnewVal.join(); // 2;\n```\n\n----\n\n### \u003ca id=\"chainfunc\"\u003e`chain(chain: (val: T) =\u003e Maybe\u003cT\u003e): Maybe`\u003c/a\u003e\n\nChain together functions that return Maybe monads:\n\n```javascript\nfunction addOne (val) {\n  return Maybe.of(val + 1);\n}\n\nconst three = Maybe.of(1)\n .chain(addOne)\n .chain(addOne);\n\n three.join(); // 3\n```\n\n----\n\n## \u003ca id=\"credit\"\u003eCredit\u003c/a\u003e\n\nCredit to [James Sinclair](https://github.com/jrsinclair) for writing [The Marvellously Mysterious JavaScript Maybe Monad](http://jrsinclair.com/articles/2016/marvellously-mysterious-javascript-maybe-monad/).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmikechabot%2Fmaybe-baby","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmikechabot%2Fmaybe-baby","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmikechabot%2Fmaybe-baby/lists"}