{"id":15902708,"url":"https://github.com/no-stack-dub-sack/basic-immutable","last_synced_at":"2026-01-21T10:37:36.907Z","repository":{"id":99475245,"uuid":"130709428","full_name":"no-stack-dub-sack/basic-immutable","owner":"no-stack-dub-sack","description":"basic immutable JavaScript objects and arrays, with a small API surface area","archived":false,"fork":false,"pushed_at":"2018-04-28T16:50:17.000Z","size":124,"stargazers_count":3,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-11T08:12:52.366Z","etag":null,"topics":["data","immutable","immutable-collections","immutable-datastructures","immutable-store","lodash","persistent-data-structure","typescript"],"latest_commit_sha":null,"homepage":null,"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/no-stack-dub-sack.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2018-04-23T14:27:28.000Z","updated_at":"2023-12-05T06:42:54.000Z","dependencies_parsed_at":"2023-07-04T17:46:56.503Z","dependency_job_id":null,"html_url":"https://github.com/no-stack-dub-sack/basic-immutable","commit_stats":{"total_commits":21,"total_committers":1,"mean_commits":21.0,"dds":0.0,"last_synced_commit":"1f9118007cb8c035760fa3a69f6ac152454e7b77"},"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/no-stack-dub-sack/basic-immutable","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/no-stack-dub-sack%2Fbasic-immutable","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/no-stack-dub-sack%2Fbasic-immutable/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/no-stack-dub-sack%2Fbasic-immutable/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/no-stack-dub-sack%2Fbasic-immutable/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/no-stack-dub-sack","download_url":"https://codeload.github.com/no-stack-dub-sack/basic-immutable/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/no-stack-dub-sack%2Fbasic-immutable/sbom","scorecard":{"id":691246,"data":{"date":"2025-08-11","repo":{"name":"github.com/no-stack-dub-sack/basic-immutable","commit":"1f9118007cb8c035760fa3a69f6ac152454e7b77"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":1.7,"checks":[{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Code-Review","score":0,"reason":"Found 0/22 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 1 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"72 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-6chw-6frg-f759","Warn: Project is vulnerable to: GHSA-v88g-cgmw-v5xw","Warn: Project is vulnerable to: GHSA-93q8-gq69-wqmw","Warn: Project is vulnerable to: GHSA-fwr7-v2mv-hh25","Warn: Project is vulnerable to: GHSA-67hx-6x53-jw92","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-cwfw-4gq5-mrqx","Warn: Project is vulnerable to: GHSA-g95f-p29q-9xw4","Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg","Warn: Project is vulnerable to: GHSA-c6rq-rjc2-86v2","Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275","Warn: Project is vulnerable to: GHSA-rq8g-5pc5-wrhr","Warn: Project is vulnerable to: GHSA-w573-4hg7-7wgq","Warn: Project is vulnerable to: GHSA-hr2v-3952-633q","Warn: Project is vulnerable to: GHSA-qrmc-fj45-qfc2","Warn: Project is vulnerable to: GHSA-fjxv-7rqg-78g4","Warn: Project is vulnerable to: GHSA-8r6j-v8pm-fqw3","Warn: Project is vulnerable to: MAL-2023-462","Warn: Project is vulnerable to: GHSA-q42p-pg8m-cqh6","Warn: Project is vulnerable to: GHSA-w457-6q6x-cgp9","Warn: Project is vulnerable to: GHSA-62gr-4qp9-h98f","Warn: Project is vulnerable to: GHSA-f52g-6jhx-586p","Warn: Project is vulnerable to: GHSA-2cf5-4w76-r9qv","Warn: Project is vulnerable to: GHSA-3cqr-58rm-57f8","Warn: Project is vulnerable to: GHSA-g9r4-xpmj-mj65","Warn: Project is vulnerable to: GHSA-q2c6-c6pm-g3gh","Warn: Project is vulnerable to: GHSA-765h-qjxv-5f44","Warn: Project is vulnerable to: GHSA-f2jv-r9rf-7988","Warn: Project is vulnerable to: GHSA-44pw-h2cw-w3vq","Warn: Project is vulnerable to: GHSA-c429-5p7v-vgjp","Warn: Project is vulnerable to: GHSA-43f8-2h32-f4cj","Warn: Project is vulnerable to: GHSA-qqgx-2p2h-9c37","Warn: Project is vulnerable to: GHSA-2pr6-76vf-7546","Warn: Project is vulnerable to: GHSA-8j8c-7jfh-h6hx","Warn: Project is vulnerable to: GHSA-896r-f27r-55mw","Warn: Project is vulnerable to: GHSA-9c47-m6qq-7p4h","Warn: Project is vulnerable to: GHSA-6c8f-qphg-qjgp","Warn: Project is vulnerable to: GHSA-4xc9-xhrj-v574","Warn: Project is vulnerable to: GHSA-x5rq-j2xg-h7qm","Warn: Project is vulnerable to: GHSA-jf85-cpcp-j695","Warn: Project is vulnerable to: GHSA-p6mc-m468-83gw","Warn: Project is vulnerable to: GHSA-29mw-wpgm-hmr9","Warn: Project is vulnerable to: GHSA-35jh-r3h4-6jhm","Warn: Project is vulnerable to: GHSA-4xcv-9jjx-gfj3","Warn: Project is vulnerable to: GHSA-f9cm-qmx5-m98h","Warn: Project is vulnerable to: GHSA-7wpw-2hjm-89gp","Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv","Warn: Project is vulnerable to: GHSA-f8q6-p94x-37v3","Warn: Project is vulnerable to: GHSA-vh95-rmgr-6w4m","Warn: Project is vulnerable to: GHSA-xvch-5gv4-984h","Warn: Project is vulnerable to: GHSA-fhjf-83wg-r2j9","Warn: Project is vulnerable to: GHSA-5fw9-fq32-wv5p","Warn: Project is vulnerable to: GHSA-hj48-42vr-x3v9","Warn: Project is vulnerable to: GHSA-hrpp-h998-j3pp","Warn: Project is vulnerable to: GHSA-6g33-f262-xjp4","Warn: Project is vulnerable to: GHSA-p8p7-x288-28g6","Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw","Warn: Project is vulnerable to: GHSA-4g88-fppr-53pp","Warn: Project is vulnerable to: GHSA-4jqc-8m5r-9rpr","Warn: Project is vulnerable to: GHSA-mf6x-7mm4-x2g7","Warn: Project is vulnerable to: GHSA-j44m-qm6p-hp7m","Warn: Project is vulnerable to: GHSA-3jfq-g458-7qm9","Warn: Project is vulnerable to: GHSA-r628-mhmh-qjhw","Warn: Project is vulnerable to: GHSA-9r2w-394v-53qc","Warn: Project is vulnerable to: GHSA-5955-9wpr-37jh","Warn: Project is vulnerable to: GHSA-qq89-hq3f-393p","Warn: Project is vulnerable to: GHSA-f5x3-32g6-xq36","Warn: Project is vulnerable to: GHSA-jgrx-mgxx-jf9v","Warn: Project is vulnerable to: GHSA-72xf-g2v4-qvf3","Warn: Project is vulnerable to: GHSA-3h5v-q93c-6h6q","Warn: Project is vulnerable to: GHSA-c4w7-xm78-47vh","Warn: Project is vulnerable to: GHSA-p9pc-299p-vxgp"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-22T02:20:50.233Z","repository_id":99475245,"created_at":"2025-08-22T02:20:50.234Z","updated_at":"2025-08-22T02:20:50.234Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28631937,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-21T04:47:28.174Z","status":"ssl_error","status_checked_at":"2026-01-21T04:47:22.943Z","response_time":86,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["data","immutable","immutable-collections","immutable-datastructures","immutable-store","lodash","persistent-data-structure","typescript"],"created_at":"2024-10-06T11:42:38.904Z","updated_at":"2026-01-21T10:37:36.886Z","avatar_url":"https://github.com/no-stack-dub-sack.png","language":"JavaScript","readme":"# basic-immutable\n\nAn unsophisticated, single-dependency, [TypeScript friendly](#basicimmutable--typescript) immutability library for creating backwards JavaScript compatible objects and arrays, with a few extra features just for fun. Under the hood, this library is really just an immutable extension of several [Lodash](https://github.com/lodash/lodash) methods, thrown together quickly and easily; nothing too fancy here :smile:\n\n### Contents\n- [Background](#background)\n- [Getting Started](#getting-started)\n    - [Installation](#installation)\n    - [Basic examples](#basic-examples)\n- [API](#api)\n    - [An important note about `BasicImmutable` arrays](#an-important-note-about-basicimmutable-arrays)\n    - [BasicImmutable \u0026 TypeScript](#basicimmutable--typescript)\n    - [Available Methods](#available-methods)\n- [Contributing](#contributing)\n\n### Background\nFor the million or so immutability libraries out there, surprisingly, I was not able to find one that suited my needs perfectly. So I'm adding one more to the mix. Here's a brief summary of my favorite features of BasicImmutable, that I've found disparately across several libraries, but never together in one:\n\n- Very [TypeScript friendly](#basicimmutable--typescript) (I had difficulty with ImmutableJS in particular for this one). Great for working with Redux apps in TypeScript, as complex types can be assigned to your state objects just as if you were working with a plain JavaScript object\n- Completely backwards JavaScript compatible, use BasicImmutable data structures in your code like any other JavaScript objects\n- Re-implements all native JavaScript array mutator methods as immutable; e.g. `Array.push()` returns a new array with items appended, instead of returning the length of the array.\n- Ability to easily strip away the API (with `toJS`), and convert to a 100% plain-old JavaScript object, in case you still find edge cases in which there are unintended side-effects (such as in AngularJS, where using other libraries broke certain functionalities for me)\n- Relatively small API surface area to learn; in addition to understanding that all array mutator methods are now immutable, there are only about 10 BasicImmutable specific methods to learn. Most of which should be very familiar to you if you've ever used Lodash.\n\nHowever, that this library is so tailored to my needs, means that it might not be right for you, or you may simply be happier with one of the alternatives. And there has not been any special attention paid to performance or speed - the library is as fast as Lodash is. Try it out if you'd like, otherwise, no big deal. My intent in publishing this, was just in case even one other person out there was facing the same struggles as I was, they might find this useful.\n\n## Getting Started\n\n### Installation\n- To install, run `yarn add basic-immutable` or `npm install --save basic-immutable`\n- TypeScript typings are included and do not need to installed separately\n\nPass your data structure to `Immutable()` and call `toJS()` to transform them back into POJO (plain-old JavaScript objects). [Full list of methods](#available-methods) and examples can be found in the [API section](#api) below.\n### Basic examples\n\n`ImmutableObject` with TypeScript:\n```ts\nimport Immutable from 'basic-immutable';\n\ninterface Community {\n  isLoading: boolean;\n  users: {\n    id: number;\n    name: string;\n  }[]\n}\n\nconst community = Immutable\u003cCommunity\u003e({\n  isLoading: true,\n  users: [{\n    id: 1,\n    name: 'Raul'\n  }, {\n    id: 2,\n    name: 'Jenny'\n  }]\n});\n\nconst updated = community\n  .merge({ isLoading: false })\n  .set('users[2]', { id: 3, name: 'Rhonda' });\n```\n\n`ImmutableArray` with JavaScript:\n```js\nconst userStatus = Immutable([\n  { name: 'Brittany', active: false },\n  { name: 'Noah', active: true },\n  { name: 'Jitendra', active: true }\n]);\n\nconst userStatus1 = userStatus.push({\n  name: 'Mikael',\n  active: false\n}, {\n  name: 'Maria',\n  active: true\n}); // returns new ImmutableArray, not length\n\nconst userStatus2 = userStatus1.set(['0', 'active'], true).delete(1);\n// the original userStatus is unchanged\n\n// is just an array with extended functionality\n// can still iterate over as normal\nfor (let el of userStatus2) {\n  console.log(el.name, el.active)\n}\n// prints:\n// 'Brittany' true\n// 'Jitendra' true\n// 'Mikael' false\n// 'Maria' true\n```\n\n## API\n\n### Available Methods:\n- ImmutableObject / ImmutableArray\n  - [get](#getpath)\n  - [set](#setpath-value)\n  - [update](#updatepath-value)\n  - [delete](#deletepath)\n  - [equals](#equals)\n  - [asMutable](#asmutable)\n  - [toJS](#tojsfrozen)\n- ImmutableObject\n  - [merge](#mergesources)\n  - [mergeTolerant](#mergetolerantsources)\n  - [toArray](#toarray)\n- ImmutableArray\n  - [pull](#pullpulldeep-values)\n  - [flatten](#flattendeep)\n  - [toObject](#toobjectkeyinitializer)\n  - [all methods](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array#Methods) available on plain old JavaScript arrays**\n\n### **An important note about `BasicImmutable` arrays\n- Arrays created with `Immutable()` are still just JavaScript arrays under the hood, which means that all of the native array methods are still available to you, and all non-mutator methods behave as normal (`filter`, `map`, `reduce`, `includes`, `indexOf`, etc.). However, all [mutator methods](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/prototype#Mutator_methods) have been re-implemented as immutable.\n- For example, `Immutable([1, 2, 3]).push(1)`, rather than returning the array's length after performing the push operation, will instead return a new `BasicImmutable` array (the original array is, of course, unmutated).\n\nA full list of the re-implemented non-mutator methods is below, __which all return new BasicImmutable arrays__:\n\n| Method     | Description                                                                                        |\n|------------|----------------------------------------------------------------------------------------------------|\n| push       | Returns a new `BasicImmutable` array with one or more elements added to the end                    |\n| pop        | Returns a new `BasicImmutable` array with the last element removed                                 |\n| shift      | Returns a new `BasicImmutable` array with the first element removed                                |\n| unshift    | Returns a new `BasicImmutable` array with one or more elements added to the front                  |\n| splice     | Returns a new `BasicImmutable` array with elements added and/or removed                            |\n| sort       | Returns a new `BasicImmutable` array with the elements sorted                                      |\n| reverse    | Returns a new `BasicImmutable` array with the order of the elements reversed                       |\n| copyWithin | Returns a new `BasicImmutable` array with a sequence of array elements copied within the array     |\n| fill       | Returns a new `BasicImmutable` array filled from a start index to an end index with a static value |\n\n### BasicImmutable \u0026 TypeScript\n\n__An important note about working with `BasicImmutable` and TypeScript:__ All methods that return a new, modified object or array will accept type arguments via the generic versions of their typings, so that a new type can be assigned should the given operation change the shape of your object or array.\n\nFor example:\n\n```ts\nconst obj = Immutable\u003c{ a: number, b: number }\u003e({ a: 6, b: 2 })\n\nconst obj1 = obj.delete('a'); // inferred type of obj1 is still ImmutableObject\u003c{ a: number; b: number; }\u003e\n```\nThis is incorrect. To ensure the object maintains type safety and accuracy, use the generic form of the method:\n```ts\nconst obj2 = obj.delete\u003c{ b: number; }\u003e('a'); // type is now ImmutableObject\u003c{ b: number; }\u003e, which is correct\n```\n\nThis might also be useful for converting an array's type, when popping, pushing, or otherwise modifying the returned array.\n```ts\nconst users = Immutable\u003cstring[]\u003e([['Pete', 'online'], ['Jared', 'offline']]);\n\n// create new array and assign tuple-like type of ImmutableArray\u003c'Jared' | 'online\u003e\n\nconst jared = users.set([1, 1], 'online').shift\u003c'Jared' | 'online'\u003e().flatten(); // ['Jared','online']\n```\nThis approach will work for all modifying methods: `set`, `update`, `delete`, `merge` (ImmutableObject only), `mergeTolerant` (ImmutableObject only), `pull` (ImmutableArray only), `fill` (ImmutableArray only), etc.\n\nOf course, if your object or array is less strictly typed to begin with, this could be a non-issue, so there is a balancing act between type-safety and what works best for you and your particular use-case:\n```ts\nconst obj = Immutable\u003c{ [key: string]: number }\u003e({ a: 6, b: 2 })\n\n// OK! but not super type-safe\nconst obj1 = obj.delete('a'); // inferred type of obj1 is still ImmutableObject\u003c{ [key: string]: number; }\u003e\n```\n\n## get(path)\nGets the value at a given path of an `ImmutableObject` or `ImmutableArray` and returns it. _Uses Lodash's `_.get()`._\n\n__Parameters:__\n\n`path` Number, path string, or path array\n\n```js\nconst arr = Immutable(['d', 'o', { a: 'o', b: 'r'}]);\nconst obj = Immutable({ a: 1, b: ['h', 9], c: ['o', 't', 'u'] });\n\nconsole.log(obj.get('b[0]')); // h\nconsole.log(obj.get(['c', '0'])); // o\n\nconsole.log(arr.get(0)); // d\nconsole.log(arr.get('2.a')); // o\nconsole.log(arr.get('2.b')); // r\n```\n:point_up: [Run](https://repl.it/@no_stack_dub_sack/GetExample) \u0026nbsp; :arrow_up: [Back to Methods List](#available-methods)\n\n## set(path, value)\nReturns a new `ImmutableObject` or `ImmutableArray` with value set at the given path. _Uses Lodash's `_.set()`._\n\n__Parameters:__\n\n`path` Number, path string, or path array\n\n`value` The value to set at the resolved path\n\n```js\nconst arr = Immutable(['a', 'b', { a: 1, b: 2}]);\nconst obj = Immutable({ a: 1, b: [3, 9], c: [['js', 't']] });\n\nconst obj1 = obj.set(['c', '0', 1], 'tools');\nconst obj2 = obj.set('b[0]', 'are').set('c', 'fun!');\n\nconst arr1 = arr.set(0, 'A');\nconst arr2 = arr1.set('2.a', 10);\n```\n:point_up: [Run](https://repl.it/@no_stack_dub_sack/SetExample) \u0026nbsp; :arrow_up: [Back to Methods List](#available-methods)\n\n## update(path, updater)\nLike `set` except accepts an updater function to produce the value to set. _Uses Lodash's `_.update()`._\n\n__Parameters:__\n\n`path` Number, path string, or path array\n\n`updater` The function to produce the updated value\n\n```js\nconst arr = Immutable(['a', 'b', { a: 1, b: 2}]);\nconst obj = Immutable({ a: 1, b: [3, 9], c: ['s', 't', 'u'] });\n\nconst obj1 = obj.update(['c', '2'], (str) =\u003e  str + ' r cool!');\nconst obj2 = obj1.update('b[0]', (n) =\u003e n * 300);\nconst arr1 = arr.update(0, (str) =\u003e str.toUpperCase());\nconst arr2 = arr1.update('2.a', (n) =\u003e n + 10);\n```\n:point_up: [Run](https://repl.it/@no_stack_dub_sack/UpdateExample) \u0026nbsp; :arrow_up: [Back to Methods List](#available-methods)\n\n## delete(path)\nReturns a new `ImmutableObject` or `ImmutableArray` with element at a given path or position removed.\n\n__TypeScript Tip:__ To maintain type-safety, be careful to re-type your object with the `delete` generic if the deletion causes a conflict with the base type originally defined or inferred for you object. See the note [here](#PLACEHOLDER) about working with BasicImmutable and TypeScript.\n\n__Parameters:__\n\n`path` Number, path string, or path array\n\nWith TypeScript:\n```ts\ninterface IObj { a: number; b: number; c: (number | object)[]; }\nconst obj = Immutable\u003cIObj\u003e({ a: 1, b: 2, c: [ 1, 2, { x: 1, y: 2 }]})\n\n// delete nested elements\nconst obj1 = obj.delete('c[2].x');\n\n// re-assign type\nconst obj2 = obj1.delete\u003c{ a: number; b: number; }\u003e('c'); // { a: 1, b: 2 }\n\nconst arr = Immutable\u003cnumber | number[]\u003e([1, 2, [3, 4, 5]]);\nconst arr1 = arr.delete([2, 1]) // [1, 2, [3, 5]]\nconst arr2 = arr1.delete\u003cnumber\u003e(2) // type ImmutableArray\u003cnumber\u003e, [1, 2]\n```\nWith JavaScript:\n```js\nconst obj = Immutable({ a: 1, b: [ 1, 2, { x: 1, y: 2 }]})\nconst arr = Immutable([1, 2, [3, 4, 5]]);\n\n// delete nested elements\nconst obj1 = obj.delete('b[2].x'); // { a: 1, b: [ 1, 2, { y: 2 }]}\nconst arr1 = arr.delete([2, 1]); // [1, 2, [3, 5]]\n```\n\n:point_up: [Run](https://repl.it/@no_stack_dub_sack/DeleteExample) \u0026nbsp; :arrow_up: [Back to Methods List](#available-methods)\n\n## equals(comparison)\nPerforms a deep comparison (excluding the basic-immutable methods) between the object and array and the given argument. _Uses Lodash's `_.equals()`._\n\n__Parameters:__\n\n`comparison` Any (but an object or array makes the most sense).\n\n```js\nconst arr = Immutable([1, 2, 3]);\nconst obj = Immutable({ a: 1, b: 2 });\n\narr.equals([1, 2, 3]); // true\nobj.equals([1, 2, 3]); // false\n```\n:point_up: [Run](https://repl.it/@no_stack_dub_sack/EqualsExample) \u0026nbsp; :arrow_up: [Back to Methods List](#available-methods)\n\n## asMutable\nConverts to mutable object or array, i.e. basic-immutable methods are still available, but mutations are allowed until another basic-immutable modifying method is called (i.e. any method that returns a new `ImmutableObject` or `ImmutableArray`).\n\n__NOTE:__ For arrays, methods that are traditionally mutator methods will still be performed immutably, and if called, will return the array to it's immutable state.\n\n__Parameters:__ None\n\n```js\nconst arr = Immutable([1, 2, 3]);\nconst obj = Immutable({ a: 1, b: 2 });\n\nconst arr1 = arr.asMutable();\narr1[0] = 'allowed';\nconsole.log(arr1.get(0)); // 'allowed'\n\nconst arr2 = arr1.push(4);\narr2[0] = 'not allowed'; // nope!\n// push() was called, the resulting array is immutable\n\nconst obj1 = obj.asMutable();\nobj1.a = 2; // { a: 2, b: 2 }\n```\n:point_up: [Run](https://repl.it/@no_stack_dub_sack/AsMutableExample) \u0026nbsp; :arrow_up: [Back to Methods List](#available-methods)\n\n## toJS(frozen?)\nConverts `ImmutableObject` or `ImmutableArray` to plain-old JavaScript and returns it (can be mutated, basic-immutable API helper methods are stripped away. To return a plain, but frozen object, pass `true`).\n\nUseful for working with front-end libraries that don't play well with instance objects (such as AngularJS, which I had difficulties with in particular when trying to use other plain-old JS immutability libraries).\n\n__Parameters:__\n\n`frozen` **_[optional]_** boolean, whether or not to return a frozen object or array.\n\n```js\nconst arr = Immutable([1, 2, 3]);\nconst obj = Immutable({ a: 1, b: 2 });\n\nconst jsArr = arr.toJS();\nconst jsObj = obj.toJS();\n\nlet props = Object.getOwnPropertyNames(jsArr);\nprops = props.concat(Object.getOwnPropertyNames(jsObj));\n\nconst isDefinitelyJustJS = !props.includes('asMutable'); // true\n\njsObj.a = 3; // can be mutated\njsArr[3] = 4; // can be mutated\n\nconst frozenJSObj = obj.toJS(true); // plain-jane JS, but cannot be mutated\nfrozenJSObj.a = 3; // throws in strict mode\n```\n:point_up: [Run](https://repl.it/@no_stack_dub_sack/ToJSExample) \u0026nbsp; :arrow_up: [Back to Methods List](#available-methods)\n\n## merge(...sources)\nMerges source object(s) into target object and returns updated target as a new `ImmutableObject`. Will throw if any of the source objects contain keys uncommon to the target object. This is valuable to prevent accidentally merging the wrong source. __TIP:__ Use TypeScript to catch this error before runtime! _Uses Lodash's `_.merge()`._\n\nUse `mergeTolerant` for a less strict merge.\n\n__Parameters:__\n\n`source` or `…sources` One or more source objects.\n\nWith TypeScript:\n```ts\nconst obj = Immutable\u003c{ a: string; b: number }\u003e({ a: 'foo', b: 2 });\n\nconst obj1 = obj.merge({ b: 3 }, { a: 'bar' })\n// { a: 'bar', b: 3 }\n\nobj.merge({ c: 3 })\n// Error! [TS] Object literal may only specify known properties, and 'c' does not exist in type 'Partial\u003c{ a: string; b: number; }\u003e'\n\nobj.merge({ b: 'baz' })\n// Error! [TS] Argument of type '{ b: string; }' is not assignable to parameter of type 'Partial\u003c{ a: string; b: number; }\u003e'\n```\nWith JavaScript:\n```js\nconst obj = Immutable({ a: 1, b: 2, c: 3 });\n\nconst obj1 = obj.merge({ a: 3 });\n// { a: 3, b: 2, c: 3 }\n\nconst obj2 = obj1.merge({ c: 5 }, { b: 4 });\n// { a: 3, b: 4, c: 5 }\n\nobj.merge({ a: 3 }, { d: 'nope!' }); // throws! key 'd' is not found on source object\n```\n:point_up: [Run](https://repl.it/@no_stack_dub_sack/MergeExample) \u0026nbsp; :arrow_up: [Back to Methods List](#available-methods)\n\n## mergeTolerant(...sources)\nLike `merge`, except this method allows source objects of different shapes (containing keys uncommon to the target object) to be merged. _Uses Lodash's `_.merge()`_.\n\n__Typescript Tip:__ If using TypeScript, have no fear, this will still be a type-safe operation. The typings instruct TypeScript to create a new intersection type from the type of your original object and the type of the source object or objects. Be explicit to avoid loose type inference by passing your new type(s) to the `mergeTolerant` generic (see example below).\n\n__Parameters:__\n\n`source` or `…sources` One or more source objects.\n\nWith TypeScript:\n```ts\nconst obj = Immutable\u003c{ a: 'yes'; b: 'no' }\u003e({ a: 'yes', b: 'no'});\n\nconst good = obj.mergeTolerant({ c: 'maybe' });\n// is inferred type { a: \"yes\"; b: \"no\"; } \u0026 { c: string; }\n\ninterface IMaybe { c: 'maybe'; }\nconst better = obj.mergeTolerant\u003cIMaybe\u003e({ c: 'maybe' });\n// is safer type { a: \"yes\"; b: \"no\"; } \u0026 { c: \"maybe\"; }\n```\nWith JavaScript:\n```js\nconst obj = Immutable({ a: 1, b: 2 });\n\nconst obj1 = obj.mergeTolerant({ c: 3 });\n// { a: 1, b: 2, c: 3 }\n```\n:point_up: [Run](https://repl.it/@no_stack_dub_sack/MergeTolerantExample) \u0026nbsp; :arrow_up: [Back to Methods List](#available-methods)\n\n## toArray\nReturns a new `ImmutableArray` array containing the values of the object's keys.\n\n__TypeScript Tip:__ If using TypeScript, and your object has been explicitly typed, e.g. `Immutable\u003c{ a: 1, b: 2 }\u003e({a: 1, b: 2});`, and no type argument is explicitly passed to the `toArray` generic, this method will return a tuple-like array, which is strictly typed to allow only the values found in your object. For a less strictly typed array, pass a type argument, e.g. `toArray\u003cnumber\u003e();`, this way you will be able to add additional data with the type `number` to your array.\n\n__Parameters:__ None\n\nWith TypeScript:\n```ts\nconst obj = Immutable({ a: 1, b: 2 })\nconst obj1 = Immutable\u003c{ a: 1, b: 2 }\u003e({a: 1, b: 2})\n\nconst arr = obj1.toArray();\n// inferred type: ImmutableArray\u003c1, 2\u003e\n\n// will allow additional 1s and 2s to be added\narr.push(1, 1, 2, 2); // OK!\n\n// but attempting to add other values will cause an error\narr.push(3); // Error!\n// [ts] Argument of type '3' is not assignable to parameter of type '1 | 2'.\n\nconst arr1 = obj1.toArray\u003cnumber\u003e();\n// type: ImmutableArray\u003cnumber\u003e, i.e. number[]\narr1.push(3, 4, 5); // OK!\n\nconst arr2 = obj.toArray() // inferred type: number[]\n// because obj1's type was inferred, not explicitly defined\n```\nWith JavaScript:\n```js\nconst obj = Immutable({ a: 1, b: 2, c: 3 });\n\nconst arr = obj.toArray(); // [1, 2, 3]\n```\n:point_up: [Run](https://repl.it/@no_stack_dub_sack/ToArrayExample) \u0026nbsp; :arrow_up: [Back to Methods List](#available-methods)\n\n## pull(deep, ...values)\nRemoves all provided values from an `ImmutableArray` using SameValueZero for equality comparisons, either from the top level array, or recursively. _Uses Lodash's `_.pull()`_.\n\n__Parameters:__\n\n`pullDeep` Indicates whether or not to pull value(s) only from the top level array, or to pull value(s) recursively.\n\nWith TypeScript:\n```ts\nconst arr = Immutable([1, 2, 3, '4', '5']);\n// inferred type ImmutableArray\u003cnumber | string\u003e, i.e. (number | string)[]\n\n// pass type argument to re-type the ImmutableArray\nconst arr1 = arr.pull\u003cnumber\u003e(false, '4', '5'); // [1, 2, 3]\n// now ImmutableArray\u003cnumber\u003e, i.e. number[]\n```\nWith JavaScript:\n```js\nconst arr = Immutable([1, 3, 3, 4, [1, 3, 3, 4, [1, 3]], 1, 3]);\n\nconst arr1 = arr.pull(false, 3); // [ 1, 4, [ 1, 3, 3, 4, [ 1, 3 ] ], 1 ]\n\nconst arr2 = arr1.pull(true, 3, 4); // [ 1, [ 1, [ 1 ] ], 1 ]\n```\n:point_up: [Run](https://repl.it/@no_stack_dub_sack/PullExample) \u0026nbsp; :arrow_up: [Back to Methods List](#available-methods)\n\n## flatten(deep?)\nFlattens `ImmutableArray` either a single level deep or recursively. _Uses Lodash's `_.flatten()`_.\n\n__Parameters:__\n\n`deep` **_[optional]_** boolean, indicates whether or not to flatten recursively.\n\nWith TypeScript:\n```ts\nconst arr = Immutable([0, 0, [1, 1], [2, 2, [3, 3]]]);\n// inferred type ImmutableArray\u003cnumber | (number | number[])[]\u003e\n\nconst flat = arr.flatten(); // [0, 0, 1, 1, 2, 2, [3, 3]]\n\n// pass type argument to re-type the ImmutableArray\nconst flatter = arr.flatten\u003cnumber\u003e(true);\n// now ImmutableArray\u003cnumber\u003e, i.e. number[]\n```\nWith JavaScript:\n```js\nconst arr = Immutable([0, 0, [1, 1], [2, 2, [3, 3]]]);\n\nconst flat = arr.flatten(); // [0, 0, 1, 1, 2, 2, [3, 3]]\n\nconst flatter = arr.flatten(true); // [0, 0, 1, 1, 2, 2, 3, 3]\n```\n:point_up: [Run](https://repl.it/@no_stack_dub_sack/FlattenExample) \u0026nbsp; :arrow_up: [Back to Methods List](#available-methods)\n\n## toObject(keyInitializer?)\nMaps over array and converts to `ImmutableObject`. Keys-value pairs are produced by the elements in the array (values) and by providing a key-initializer argument as described below (keys).\n\n__Parameters:__\n\n`keyInitializer` **_[optional]_** A single-letter string, equivalent to `/[a-zA-Z]/`, number, or function synonymous with an `Array.map` callback.\n- If provided a letter or number, keys will begin with that letter or number and be incremented for each element of the array.\n- To designate custom keys, provide an `Array.map` callback instead (see example below).\n- If undefined, keys will be equal to their values (numbers) or the stringified version of their values. Both `number` and `string` key indexers will be allowed.\n\nWith TypeScript:\n```ts\nconst arr = Immutable(['a', 'b', 'c', 'd']);\nconst nested = Immutable([[1, 2], [3, 4], [5, 6], [7, 8]]);\n\n/******** with no `keyInitializer` argument: ***********/\nconst obj1 = arr.toObject\u003c{ [key: string]: string; }\u003e();\n// { a: 'a', b: 'b', c: 'c', d: 'd' }\n// pass type argument to indicate correct key indexer, default is { [key: number]: T; [key: string]: T; }\n\n\n/******** with string `keyInitializer` argument: ***********/\nconst obj2 = nested.toObject\u003c{ [key: string]: number[]; }\u003e('A');\n// { A: [1, 2], B: [3, 4], C: [5, 6], D: [7, 8] }\n\n// same as above with more strict typing\ninterface ObjFromArray { A: number[]; B: number[]; C: number[]; D: number[]; };\nconst obj2 = nested.toObject\u003cObjFromArray\u003e('A');\n// { A: [1, 2], B: [3, 4], C: [5, 6], D: [7, 8] }\n\n\n/******** with number `keyInitializer` argument: ***********/\nconst obj4 = nested.toObject\u003c{ [key: number]: number[]; }\u003e(1);\n// { 1: [1, 2], 2: [3, 4], 3: [5, 6], 4: [7, 8] }\n\n\n/******** with Array.map `keyInitializer` argument: ***********/\nconst obj5 = nested.toObject\u003c{ [key: number]: number[]; }\u003e((arr) =\u003e arr[0] + arr[1]);\n// { 3: [1, 2], 7: [3, 4], 11: [5, 6], 15: [7, 8] }\n\nconst obj6 = arr.toObject\u003c{ [key: string]: string; }\u003e((el) =\u003e el.toUpperCase());\n// { A: 'a', B: 'b', C: 'c', D: 'd' }\n```\nWith JavaScript:\n```js\nconst arr = Immutable(['a', 'b', 'c', 'd']);\nconst nested = Immutable([[1, 2], [3, 4], [5, 6], [7, 8]]);\n\n/******** with no `keyInitializer` argument: ***********/\nconst obj1 = arr.toObject();\n// { a: 'a', b: 'b', c: 'c', d: 'd' }\n\n\n/******** with string `keyInitializer` argument: ***********/\nconst obj2 = nested.toObject('A');\n// { A: [1, 2], B: [3, 4], C: [5, 6], D: [7, 8] }\n\n\n/******** with number `keyInitializer` argument: ***********/\nconst obj3 = nested.toObject(1);\n// { 1: [1, 2], 2: [3, 4], 3: [5, 6], 4: [7, 8] }\n\n\n/******** with Array.map `keyInitializer` argument: ***********/\nconst obj4 = nested.toObject((arr) =\u003e arr[0] + arr[1]);\n// { 3: [1, 2], 7: [3, 4], 11: [5, 6], 15: [7, 8] }\n\nconst obj5 = arr.toObject((el) =\u003e el.toUpperCase());\n// { A: 'a', B: 'b', C: 'c', D: 'd' }\n```\n:point_up: [Run](https://repl.it/@no_stack_dub_sack/ToObjectExample) \u0026nbsp; :arrow_up: [Back to Methods List](#available-methods)\n\n## Contributing\nI slapped this together pretty quick, and it's not meant to be fancy or a miraculous feat of programming. That said, I'm sure there's still plenty of room for improvement. Contributing guidelines will be added soon, but for now, if there's any interest in contributing, please open an issue!\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fno-stack-dub-sack%2Fbasic-immutable","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fno-stack-dub-sack%2Fbasic-immutable","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fno-stack-dub-sack%2Fbasic-immutable/lists"}