{"id":21844227,"url":"https://github.com/baileympearson/iterable-ts","last_synced_at":"2026-02-13T23:34:17.369Z","repository":{"id":57278484,"uuid":"361162077","full_name":"baileympearson/iterable-ts","owner":"baileympearson","description":"A Typescript library providing flexible and composable iterator operations.","archived":false,"fork":false,"pushed_at":"2022-03-21T16:38:07.000Z","size":40117,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-08-02T11:59:38.204Z","etag":null,"topics":["functional-programming","iterables","typescript"],"latest_commit_sha":null,"homepage":"https://baileympearson.github.io/iterable-ts","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/baileympearson.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"code-of-conduct.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-04-24T12:57:32.000Z","updated_at":"2023-12-30T09:47:12.000Z","dependencies_parsed_at":"2022-09-18T09:14:16.828Z","dependency_job_id":null,"html_url":"https://github.com/baileympearson/iterable-ts","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/baileympearson/iterable-ts","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/baileympearson%2Fiterable-ts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/baileympearson%2Fiterable-ts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/baileympearson%2Fiterable-ts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/baileympearson%2Fiterable-ts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/baileympearson","download_url":"https://codeload.github.com/baileympearson/iterable-ts/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/baileympearson%2Fiterable-ts/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29423534,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-13T22:20:51.549Z","status":"ssl_error","status_checked_at":"2026-02-13T22:20:49.838Z","response_time":78,"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":["functional-programming","iterables","typescript"],"created_at":"2024-11-27T22:18:46.853Z","updated_at":"2026-02-13T23:34:17.343Z","avatar_url":"https://github.com/baileympearson.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# iterable-ts\n\nThis library is still a work-in-progress!\n\nDocumentation: https://github.com/baileympearson/iterable-ts\n\n## What is iterable-ts?\n\niterable-ts is a simple, flexible library for working with syncronous iterators in Javascript. The intention\nis to provide a small set of functions that can operate on all iterators and iterables. There are other libraries\nthat provide similar functionality, but I found none that satisfied the following design goals (so naturally, I\nreinvented the wheel)\n\n### Prioritizes reusability and composability\n\nMany libraries, such as wu.js, rely on method chaining. This is inherently less composible than free functions. For\nexample, consider the following using wu.js:\n\n```js\nconst source = [1, 2, 3]\nconst result = wu(source)\n  .map(x =\u003e x * 2)\n  .filter(x =\u003e x \u003e 5)\nfor (const value in result) {\n  console.log(result)\n}\n```\n\nThe source (`wu(source)`) is inherently coupled to the logic (`map(x =\u003e x * 2).filter(x =\u003e x \u003e 5)`). Suppose we wanted\nto reuse the logic of filtering out all doubled values that are greater than 5. In wu, we'd have to abstract this to\na function\n\n```js\nfunction doubledGreaterThan5(source) {\n  return wu(source)\n    .map(x =\u003e x * 2)\n    .filter(x =\u003e x \u003e 5)\n}\n```\n\nCompare this to the curried, free function version:\n\n```ts\n// declare the same function as before\nconst doubledGreaterThan5 = compose(\n  filter(x =\u003e x \u003e 5),\n  map(x =\u003e x * 2)\n)\nconst source = [1, 2, 3]\nconst result = doubledGreaterThan5(source)\nfor (const value in source) {\n  console.log(result)\n}\n```\n\n- Uses the concept of iterators as its base abstraction\n\nSome libraries, such as rambda.js, use more complicated functional programming constructs as the base abstraction. For\nexample, the `map` function in rambda.js takes a `Functor` and returns a \"`Functor` of the same shape\". In a flexible,\ninterpreted language like Javascript, I wanted to model the library off of the approach of Clojure. Every standard\nfunction returns an iterable, which can be turned into native Javascript structures as desired.\n\n```ts\nmap(x =\u003e x * 2, range(5)) // Generator\u003cnumber\u003e\ninto(\n  'array',\n  map(x =\u003e x * 2, range(5))\n) // [0, 2, 4, 6, 8]\n```\n\n### Focuses on simplicity\n\nMany libraries attempt to solve multiple problems at once or introduce multiple abstractions. For example, IxJS provides operators\nfor both synchronous and asynchronous iterators, as well as providing multiple functions such as `of`, to allow iterator operations\non primitive values. There is nothing wrong with this approach. Instead, iterable-ts is focused purely on synchronous iterators.  \nIt also does not provide functions to elevate non-iterable values into iterators (although, feel free to write these yourself\nif you'd like. They're easy to write using generator functions).\n\n## Installation\n\nnotes to follow here\n\n## Why use iterable-ts?\n\niterable-ts is intended to be more flexible than the native iterator operations. All the functions\nincluded operate solely on Iterables and therefore work on all iterable types. For example:\n\n```ts\nconst array = [1, 2, 3, 4]\nconst set = new Set([1, 2, 3, 4])\nfunction* iterable() {\n  yield 1\n  yield 2\n  yield 3\n  yield 4\n}\n\nconst double = (x: number) =\u003e x * 2\n\n// all of the following are valid\nmap(double, array)\nmap(double, set)\nmap(double, iterable)\n```\n\nSince all the core operations produce iterables, a utility function is provided\nto easily convert iterables into native Javascript data structures:\n\n```ts\nfunction* iterable() {\n  yield 1\n  yield 2\n  yield 3\n}\ninto('array', iterable()) // [1,2,3]\ninto('set', iterable()) // Set(1,2,3)\n\n// coming soon as well\nfunction* key_value_pairs() {\n  yield ['name', 'john']\n  yield ['age', 23]\n  yield ['occupation', 'space ship pilot']\n}\n\ninto('object', key_value_pairs()) // { name: 'john', age: 23, occupation: \"space ship pilot\" }\n```\n\n## Examples\n\nHere I attempt to illustrate the power versitility and power of functional-ts. Not all of these examples are\nas clean or immediatley understandable as their imperitive counterparts.\n\n### Print the first 50 fibonacci numbers\n\n```ts\nconst fib = iterate(([a, b]) =\u003e [b, a + b], [0, 1])\nconst first_50_fib = take(50, fib)\nfor (const value of first_50_fib) {\n  console.log(value)\n}\n```\n\n### Build testable, composible logic pipelines\n\n```ts\n/**\n * print the square of the first 10 even fibonacci numbers after the first 10 odd fibonacci numbers\n */\n\n// `compose` composes functions backwards - so in this case the `map` is composed inside the `skipWhile`, and the `skipWhile` is composed inside the `scan`\nconst skipTenOdd = compose(\n  map(([value, _]) =\u003e value),\n  skipWhile(([value, count]) =\u003e count \u003c 10),\n  scan((n: number, accum: number) =\u003e {\n    if (n % 2 === 0) {\n      return accum\n    }\n    return accoum + 1\n  }, 0)\n)\n\nconst isEven = (x: number) =\u003e x % 2 === 0\n\n// don't like how `compose` works backwards?  Pipe does the same thing as compose, but does it top-to-bottom\nconst pipeline = pipe(\n  skipTenOdd,\n  filter(isEven),\n  take(10),\n  map((x: number) =\u003e x * x)\n)\n\nconst fib = iterate(([a, b]) =\u003e [b, a + b], [0, 1])\n\nfor (const value of pipeline(fib)) {\n  console.log(value)\n}\n```\n\n### Build logic pipelines\n\n```ts\ninterface User {\n  name: string\n  age: number\n}\n\nconst firstOver23 = find((user: User) =\u003e user.age \u003e 21)\n\n// print NAME:age for all users over 21.  useful? probably not.\n//    illustrative of the flexibility of compose? probably.\nconst pipeline = compose(\n  map(({ name, age}: User) =\u003e `${name}:${age}`)\n  map((user: User) =\u003e { ...user, name: user.name.toUpperCase() })\n  firstOver32\n)\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbaileympearson%2Fiterable-ts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbaileympearson%2Fiterable-ts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbaileympearson%2Fiterable-ts/lists"}