Safe and idiomatic TypeScript types to handle null, error, and async code handling: Maybe, Result, and Task types that are really nice.
Safe and idiomatic TypeScript types to handle null, error, and async code handling: Maybe, Result, and Task types that are really nice.
True Myth provides safe, idiomatic null, error, and async code handling in TypeScript, with Maybe, Result, and Task types that are really nice.
README • API docs • Source • Intro blog post
## Overview True Myth provides standard, type-safe wrappers and helper functions to help you with three _extremely_ common cases in programming: - not having a value - having a _result_ where you need to deal with either success or failure - having an asynchronous operation which may fail You could implement all of these yourself – it's not hard! – but it's much easier to just have one extremely well-tested library you can use everywhere to solve this problem once and for all. See [the docs](https://true-myth.js.org) for setup, guides, and API docs! ### Contents - [Requirements](#requirements) - [Compatibility](#compatibility) - [Basic bundle size info](#basic-bundle-size-info) ## Requirements - TS 5.3+ - `tsconfig.json`: - `moduleResolution`: use `"Node16"` or later - `strict: true` - `package.json` - `type: "module"` (or else use `import()` to import True Myth into a commonJS build) For details on using a pure ES modules package in TypeScript, see [the TypeScript handbook's guide](https://www.typescriptlang.org/docs/handbook/esm-node.html). ## Compatibility This project follows the current draft of [the Semantic Versioning for TypeScript Types][semver] specification. - **Currently supported TypeScript versions:** 5.3–6.0 - **Compiler support policy:** [simple majors][sm] - **Public API:** all published, documented types not in a `-private` module and not marked as `@internal` or `@private` are public [semver]: https://www.semver-ts.org [sm]: https://www.semver-ts.org/formal-spec/5-compiler-considerations.html#simple-majors ## Basic bundle size info Size of the ESM build without tree-shaking (yes, these are in *bytes*: this is a pretty small library!): | file | size (B) | terser[^terser] (B) | terser and brotli[^brotli] (B) | | ------------------ | -------- | ------------------- | ------------------------------ | | -private/utils.js | 942 | 358 | 175 | | index.js | 644 | 352 | 122 | | maybe.js | 23052 | 3838 | 943 | | result.js | 21376 | 4257 | 1034 | | standard-schema.js | 5984 | 758 | 318 | | task/delay.js | 3901 | 649 | 259 | | task.js | 59937 | 7629 | 2036 | | test-support.js | 473 | 142 | 89 | | toolbelt.js | 3739 | 886 | 278 | | unit.js | 656 | 58 | 57 | | **total[^total]** | 120704 | 18927 | 5311 | Notes: - The unmodified size *includes comments*. - Thus, running through Terser gets us a much more realistic size: about 18.1KB to parse. - The total size across the wire of the whole library will be ~5.2KB. - This is all tree-shakeable to a significant degree: you should only have to “pay for” the types and functions you actually use, directly or indirectly. If your production bundle does not import or use anything from `true-myth/test-support`, you will not pay for it, for example. However, some parts of the library do depend directly on other parts: for example, `toolbelt` uses exports from `result` and `maybe`, and `Task` makes extensive use of `Result` under the hood. In detail, here are the dependencies of each module: | Module | Depends on | | -------------------- | ------------------------------------------------------------ | | `index.js` | All, but as tree-shakeable as possible | | `maybe.js` | `unit.js`, `-private/utils.js` | | `result.js` | `unit.js`, `-private/utils.js` | | `standard-schema.js` | `task.js`, `result.js` | | `task.js` | `result.js`, `unit.js`, `task/delay.js`, `-private/utils.js` | | `task/delay.js` | None | | `test-support.js` | `maybe.js`, `result.js` | | `toolbelt.js` | `maybe.js`, `result.js`, `-private/utils.js` | - This intentionally excludes the ESLint plugin contents, which should not be part of an production bundle. [^terser]: Using [terser](https://github.com/terser/terser) 5.46.2 with `--compress --mangle --mangle-props`. [^brotli]: Generated by running `gzip -kq11` on the result of the `terser` invocation. [^total]: This is just the sum of the previous lines. Real-world bundle size is a function of what you actually use, how your bundler handles tree-shaking, and how the results of bundling compresses. Notice that sufficiently small files can end up _larger_ after compression; this stops being an issue once part of a bundle. ### Inspiration The design of True Myth draws heavily on prior art; essentially nothing of this is original – _perhaps_ excepting the choice to make `Maybe.of` handle `null` and `undefined` in constructing the types. In particular, however, True Myth draws particular inspiration from: - Rust's [`Option`][rs-option] and [`Result`][rs-result] types and their associated methods - Folktale's [`Maybe`][ft-maybe] and [`Result`][ft-result] implementations - Elm's [`Maybe`][elm-maybe] and [`Result`][elm-result] types and their associated functions [rs-option]: https://doc.rust-lang.org/stable/std/option/ [rs-result]: https://doc.rust-lang.org/stable/std/result/ [ft-maybe]: http://folktale.origamitower.com/api/v2.0.0/en/folktale.maybe.html [ft-result]: http://folktale.origamitower.com/api/v2.0.0/en/folktale.result.html [elm-maybe]: http://package.elm-lang.org/packages/elm-lang/core/5.1.1/Maybe [elm-result]: http://package.elm-lang.org/packages/elm-lang/core/5.1.1/ResultNo open issues yet, or sync has not completed.