{"id":30043908,"url":"https://github.com/hotequil/proposal-filter-groups","last_synced_at":"2026-01-20T17:02:53.941Z","repository":{"id":305771766,"uuid":"1021809162","full_name":"hotequil/proposal-filter-groups","owner":"hotequil","description":"TC39 proposal to implement the Array.prototype.filterGroups.","archived":false,"fork":false,"pushed_at":"2025-08-03T18:50:30.000Z","size":42,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-09-08T01:35:40.001Z","etag":null,"topics":["array","ecmascript","filter","filter-groups","groups","javascript","tc39","typescript"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/@hotequil/proposal-filter-groups","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/hotequil.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-07-18T01:47:18.000Z","updated_at":"2025-08-03T18:44:49.000Z","dependencies_parsed_at":"2025-07-21T23:27:26.624Z","dependency_job_id":"5b0afcc6-a1d5-44df-b69f-36b1e488924a","html_url":"https://github.com/hotequil/proposal-filter-groups","commit_stats":null,"previous_names":["hotequil/proposal-filter-groups"],"tags_count":2,"template":false,"template_full_name":"tc39/template-for-proposals","purl":"pkg:github/hotequil/proposal-filter-groups","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hotequil%2Fproposal-filter-groups","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hotequil%2Fproposal-filter-groups/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hotequil%2Fproposal-filter-groups/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hotequil%2Fproposal-filter-groups/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hotequil","download_url":"https://codeload.github.com/hotequil/proposal-filter-groups/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hotequil%2Fproposal-filter-groups/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28607624,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-20T16:10:39.856Z","status":"ssl_error","status_checked_at":"2026-01-20T16:10:39.493Z","response_time":117,"last_error":"SSL_read: 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":["array","ecmascript","filter","filter-groups","groups","javascript","tc39","typescript"],"created_at":"2025-08-07T05:49:56.600Z","updated_at":"2026-01-20T17:02:53.915Z","avatar_url":"https://github.com/hotequil.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Filter groups proposal\n\nTC39 proposal to implement the `Array.prototype.filterGroups`.\n\n![Proposal Stage 0](https://img.shields.io/badge/Proposal-Stage--0-blue)\n![Version](https://img.shields.io/npm/v/@hotequil/proposal-filter-groups.svg)\n![Downloads](https://img.shields.io/npm/dt/@hotequil/proposal-filter-groups.svg)\n![License](https://img.shields.io/npm/l/@hotequil/proposal-filter-groups)\n\n![npm](https://nodei.co/npm/@hotequil/proposal-filter-groups.png?downloads=true\u0026downloadRank=true\u0026stars=true)\n\n## Reason\n\nThe motivation behind this [proposal](https://es.discourse.group/t/implement-the-array-prototype-filtergroups/2407) is to simplify and enhance the process of filtering arrays into multiple distinct groups within JavaScript. Currently, filtering items based on various conditions typically involves multiple calls to [Array.prototype.filter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter), which can result in verbose, less readable and potentially less efficient code.\n\nWhile [Object.groupBy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/groupBy) offers a grouping mechanism, it relies on a single callback function that categorizes items into groups. This approach may reduce code clarity, especially when handling multiple, complex filtering criteria.\n\nThis proposal introduces `Array.prototype.filterGroups`, a method that accepts multiple callback functions and returns an array of filtered groups accordingly. This method can be invoked directly on any array instance, promoting cleaner and more expressive code.\n\nJavaScript provides a rich set of [Array methods](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array). However, when multiple, differentiated filters are needed, developers often resort to external libraries, custom helper functions or repetitive filter calls. This proposal seeks to offer a native, elegant solution to this common use case.\n\nI've developed this proposal with the intention to contribute to the JavaScript community and the language specification. You can see the [package in npm](https://www.npmjs.com/package/@hotequil/proposal-filter-groups).\n\n## How it works\n\n1. It receives one or more **functions (callbacks)** that return a **boolean**;\n2. It returns the filtered **arrays** inside a parent **array**.\n\n## Installation\n\nInstall the package using [npm](https://www.npmjs.com) or another package manager you want.\n\n```shell\nnpm install @hotequil/proposal-filter-groups\n```\n\n## Usage\n\nImport the polyfill in the main, index or app file of your project.\n\n```TypeScript\nimport \"@hotequil/proposal-filter-groups\";\n```\n\n## Typical cases\n\nFollow the examples in TypeScript below.\n\n```TypeScript\n// Imports omitted…\n\nexport const vehicles: Vehicle[] = [\n  { name: \"Toyota Corolla\", type: \"sedan\" },\n  { name: \"Honda Fit\", type: \"hatch\" },\n  { name: \"Honda Civic\", type: \"sedan\" },\n  { name: \"Honda CRV\", type: \"suv\" },\n  { name: \"Toyota Etios\", type: \"hatch\" },\n  { name: \"Honda Odyssey\", type: \"van\" },\n  { name: \"Toyota Dyna\", type: \"truck\" },\n  { name: \"Toyota SW4\", type: \"suv\" }\n];\n\nconst [sedanVehicles, hatchVehicles, suvVehicles, otherVehicles] =\n  vehicles.filterGroups(\n    // You can use the index and array parameters too, it helps to mix many conditions\n    ({ type }, _index, _array) =\u003e type === \"sedan\",\n    vehicle =\u003e vehicle.type === \"hatch\",\n    vehicle =\u003e vehicle.type === \"suv\"\n  );\n// [\n//   [\n//     { name: \"Toyota Corolla\", type: \"sedan\" },\n//     { name: \"Honda Civic\", type: \"sedan\" }\n//   ],\n//   [\n//     { name: \"Honda Fit\", type: \"hatch\" },\n//     { name: \"Toyota Etios\", type: \"hatch\" }\n//   ],\n//   [\n//     { name: \"Honda CRV\", type: \"suv\" },\n//     { name: \"Toyota SW4\", type: \"suv\" }\n//   ],\n//   [\n//     { name: \"Honda Odyssey\", type: \"van\" },\n//     { name: \"Toyota Dyna\", type: \"truck\" }\n//   ]\n// ]\n\n// The first callbacks have preference\nconst [vehiclesWithName, vehiclesWithType] =\n  vehicles.filterGroups(\n    ({ name }) =\u003e name.length \u003e 0,\n    ({ type }) =\u003e type.length \u003e 0\n  );\n// [\n//   [\n//     { name: \"Toyota Corolla\", type: \"sedan\" },\n//     { name: \"Honda Fit\", type: \"hatch\" },\n//     { name: \"Honda Civic\", type: \"sedan\" },\n//     { name: \"Honda CRV\", type: \"suv\" },\n//     { name: \"Toyota Etios\", type: \"hatch\" },\n//     { name: \"Honda Odyssey\", type: \"van\" },\n//     { name: \"Toyota Dyna\", type: \"truck\" },\n//     { name: \"Toyota SW4\", type: \"suv\" }\n//   ],\n//   []\n// ]\n\n// It'll throw a TypeError, it isn't allowed use numbers in callbacks\nvehicles.filterGroups(\n  () =\u003e true,\n  () =\u003e true,\n  1,\n  () =\u003e true\n)\n\n// It'll throw a TypeError, it isn't allowed use strings in callbacks\nvehicles.filterGroups(\n  () =\u003e true,\n  () =\u003e true,\n  \"type\",\n  () =\u003e true\n)\n\n// It'll throw a TypeError, it isn't allowed use booleans in callbacks\nvehicles.filterGroups(\n  () =\u003e true,\n  () =\u003e true,\n  true,\n  () =\u003e true\n)\n\n// It'll throw a TypeError, it isn't allowed use objects in callbacks\nvehicles.filterGroups(\n  () =\u003e true,\n  () =\u003e true,\n  {},\n  () =\u003e true\n)\n\nexport const users: User[] = [\n  { name: \"Oliver\", status: { name: \"active\" } },\n  { name: \"Henry\", status: { name: \"inactive\" } },\n  { name: \"Thomas\", status: { name: \"active\" } }\n];\n\nconst [activeUsers, inactiveUsers] = users.filterGroups(\n  user =\u003e user.status.name === \"active\"\n);\n// [\n//   [\n//     { name: \"Oliver\", status: { name: \"active\" } },\n//     { name: \"Thomas\", status: { name: \"active\" } }\n//   ],\n//   [\n//     { name: \"Henry\", status: { name: \"inactive\" } }\n//   ]\n// ]\n```\n\n## Performance\n\nTest the [performance.ts](polyfill/performance.ts) file.\n\n```TypeScript\nconst numbers = Array.from(\n  { length: 1_000_000 },\n  (_, index) =\u003e index - 500_000\n);\n\n// 21.214ms\nconst [_negatives, _evens, _odds] = numbers.filterGroups(\n  number =\u003e number \u003c 0,\n  number =\u003e number % 2 === 0,\n  number =\u003e number % 2 !== 0\n);\n\n// 31.29ms\nconst { _negatives1, _evens1, _odds1 } = Object.groupBy(numbers, number =\u003e {\n  if (number \u003c 0) return \"_negatives1\";\n  if (number % 2 === 0) return \"_evens1\";\n  if (number % 2 !== 0) return \"_odds1\";\n\n  return \"others\"\n});\n\n// 31.463ms\nconst _negatives2 = numbers.filter(number =\u003e number \u003c 0);\nconst _evens2 = numbers.filter(number =\u003e number \u003e= 0 \u0026\u0026 number % 2 === 0);\nconst _odds2 = numbers.filter(number =\u003e number \u003e= 0 \u0026\u0026 number % 2 !== 0);\n```\n\n## Similar methods\n\nThere are some similar methods, but they are not exactly the same as this proposal.\n\n| Method name                                                                                                             | Responsible |\n| ----------------------------------------------------------------------------------------------------------------------- | ----------- |\n| [Object.groupBy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/groupBy)       | Native      |\n| [Array.prototype.filter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) | Native      |\n| [\\_.groupBy](https://lodash.com/docs#groupBy)                                                                           | Lodash      |\n| [\\_.partition](https://lodash.com/docs#partition)                                                                       | Lodash      |\n\n## Proposer\n\n- Author: [@hotequil](https://github.com/hotequil);\n- Champion(s): _no one at the moment_.\n\n_This repository there isn't other third dependency, see the [package.json](package.json)._\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhotequil%2Fproposal-filter-groups","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhotequil%2Fproposal-filter-groups","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhotequil%2Fproposal-filter-groups/lists"}