# true-myth for explicit null, error, and async handling in TypeScript

> True Myth is a TypeScript library built around Maybe, Result, and Task for representing absent values, recoverable failures, and asynchronous operations that may fail. Its main adoption cost is the need to adopt explicit types throughout the surrounding TypeScript code.

**true-myth/true-myth** — Safe and idiomatic TypeScript types to handle null, error, and async code handling: Maybe, Result, and Task types that are really nice.

- Repository: https://github.com/true-myth/true-myth
- Website: https://true-myth.dev
- Stars: 1,369 · Forks: 37
- Language: TypeScript
- License: MIT
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/true-myth-true-myth

## True Myth's type-level problem space

True Myth targets three recurring situations that TypeScript can represent only indirectly by default. Maybe addresses the absence of a value. Result addresses an operation that can produce either a successful value or a failure. Task addresses an asynchronous operation that may fail. The README describes these as common programming cases rather than domain-specific utilities, so the library is intended for application code that repeatedly handles boundaries such as optional records, fallible operations, and promises.

The design is useful when the distinction between failure and an ordinary value should survive function signatures. A nullable API can otherwise be passed onward without making the caller confront the possibility of absence. A thrown error can escape a function whose return type does not mention failure. A promise can be awaited successfully even though its eventual result is an error value. True Myth gives those states named forms through Maybe, Result, and Task.

That does not make ordinary null checks or exceptions disappear from a project. The README presents these wrappers as standard, type-safe ways to model the cases, not as replacements for every JavaScript value. A field that can reasonably be null may still be clearer as a direct nullable type in some interfaces. The trade-off is whether the added abstraction gives the application enough information to enforce correct handling later. If a codebase does not propagate the type or does not inspect the relevant variant, the wrapper adds syntax without adding safety.

## Maybe, Result, and Task module boundaries

The package is organized around separate modules for its central abstractions. The repository layout includes `maybe.js`, `result.js`, and `task.js`, with related support modules such as `unit.js`, `task/delay.js`, `toolbelt.js`, and `standard-schema.js`. The package exports include the root module and additional paths, so consumers can use the package entry point or import a specific public module according to the API documentation.

The module dependencies described in the README are important for bundle planning. `maybe.js` depends on `unit.js` and private utilities. `result.js` has the same direct dependencies. `task.js` depends on `result.js`, `unit.js`, `task/delay.js`, and private utilities. `toolbelt.js` uses exports from `result` and `maybe`. The root `index.js` includes the library's exports, although the README says those exports are designed to be as tree-shakeable as possible.

This structure means importing `Task` can bring more behavior into a production bundle than importing only `Maybe`. The README specifically says that applications should pay only for functions and types they use, directly or indirectly, and gives `true-myth/test-support` as an example of code that should not enter a production bundle when it is unused. Bundle results will still depend on the bundler, import path, exports, and tree-shaking behavior. The repository's size table is useful context, but it is not a measurement of every consuming application.

## TypeScript, ESM, and compiler compatibility

True Myth requires TypeScript 5.3 or later. The README lists supported TypeScript versions as 5.3 through 6.0 and describes a compiler support policy based on simple majors. Its package configuration uses `"type": "module"`, and the published entry points point to ESM JavaScript with separate declaration files. The package also exposes an ESLint plugin through `./eslint-plugin`, while private modules are excluded through the `./-private/*` export mapping.

The project expects a particular TypeScript setup. The README specifies `moduleResolution` as `"Node16"` or later and `strict: true`. A package using the normal package configuration should also set `package.json`'s `"type": "module"`; for a CommonJS build, the README points to using `import()` to import True Myth. That distinction matters because the library is an ES module package, and changing only the dependency does not automatically make an existing project compatible with its module model.

The stated compatibility policy also has a public API boundary. Published, documented types are public unless they are in a `-private` module or marked `@internal` or `@private`. Consumers who need dependable upgrade behavior should distinguish those documented exports from private implementation files. The README references the Semantic Versioning for TypeScript Types specification rather than claiming compatibility solely from the package version number.

## Installing True Myth and finding the first API example

The README directs readers to the documentation at `https://true-myth.js.org` for setup, guides, and API documentation. It names the npm package as `true-myth`, but the repository text does not show an installation command or first-use code example. 

A new user should begin with the linked documentation's setup instructions, then verify the local `tsconfig.json` against the documented requirements. The repository's `package.json` identifies the package name as `true-myth`, version `9.4.0`, and the root export as the package entry point. The `build` script uses `tsc --project ts/publish.tsconfig.json`, while the development test command is `vitest run`. Those scripts are repository scripts, not application installation steps, so they should not be treated as a setup guide for consumers.

The first real use should be selected from the API documentation rather than guessed here. A project looking to represent an optional value should start with Maybe, one handling success and failure should start with Result, and one composing fallible asynchronous work should start with Task. This selection matters because the three abstractions solve different problems. Choosing Task for a synchronous missing value adds async machinery without addressing the actual issue.

## Bundle size, tree-shaking, and maintenance cost

The README reports a total unminified ESM size of 120,704 bytes, including comments. After the documented Terser and Brotli processing, the listed total is 18,927 bytes and 5,311 bytes respectively. The largest listed module is `task.js`, at 59,937 bytes unminified and 7,629 bytes after Terser. `result.js` and `maybe.js` are also substantial compared with the small entry and utility modules. These figures describe the repository's listed build artifacts, not the final size of an application.

The documented dependency graph provides a more actionable warning. `Task` makes extensive use of `Result`, and `toolbelt` depends on both `Result` and `Maybe`. An application may therefore need to account for indirect code even when it imports only one abstraction. Tree-shaking can remove unused exports, but the README does not promise that every import pattern has the same result. Package consumers should inspect their own production bundle after choosing entry points and helpers.

The repository is not archived, and the last push was on 2026-10-06. That supports describing the project as recently pushed, but it does not prove compatibility with every future compiler or dependency change. The license is MIT. The license permits use under its terms, but consumers still need to review the repository's `LICENSE` file for the actual obligations and notices. Upgrade work is also affected by the documented TypeScript range, ESM requirements, and the possibility that public type signatures affect downstream inference.

## When True Myth is the wrong abstraction

True Myth is a poor fit for a project that cannot yet use TypeScript 5.3 with `strict: true` and `moduleResolution` set to `"Node16"` or later. Its ESM packaging also creates friction for applications whose existing build and module conventions are not compatible with an ES module dependency. In that situation, the cost is not limited to adding a package. The project must align its compiler and module configuration first.

It is also a poor fit when nullable values are an intentional part of a small public API and the team wants callers to handle them with ordinary TypeScript syntax. Maybe is most useful when the application is prepared to carry the presence or absence of a value through its types. If the library is introduced at only one layer while the rest of the system continues to use loose nullable conventions, the resulting boundary may not improve correctness.

A real alternative is to model the same states with TypeScript unions, nullable and optional fields, exceptions, and `Promise` results. That approach keeps the dependency footprint smaller and can be easier to understand in a small codebase. True Myth's different approach is to standardize those cases as dedicated abstractions with named types and module-level APIs. The choice is therefore architectural: use True Myth when explicit failure modeling is worth the migration and learning cost; keep the native approach when the application does not need that consistency.

## Conclusion

True Myth fits TypeScript projects that want failure states represented in their types rather than scattered through undefined checks, thrown exceptions, or ad hoc async handling. It is less suitable for codebases that have not adopted strict TypeScript settings or that expect a drop-in replacement for ordinary nullable values. Before adoption, check the TypeScript version, module resolution, ESM configuration, and the API documentation for the specific Maybe, Result, or Task operations your application needs.

## FAQ

### What does True Myth provide in TypeScript?

True Myth provides Maybe, Result, and Task types for modeling missing values, successful or failed operations, and asynchronous operations that may fail. It is aimed at TypeScript developers who want those states represented explicitly.

### What are the TypeScript requirements for True Myth?

The README requires TypeScript 5.3 or later, `strict: true`, and `moduleResolution` set to `"Node16"` or later. It also expects an ES module package setup unless the project uses `import()` for a CommonJS build.

### Does True Myth have a large effect on bundle size?

The README says the library is tree-shakeable to a significant degree and that applications should pay for the parts they use directly or indirectly. It lists 120,704 bytes before tree-shaking and 5,311 bytes after the documented Terser and Brotli processing, but actual application size depends on imports and bundling.

## Sources

- [License: MIT](https://github.com/true-myth/true-myth/blob/main/LICENSE)
- [Project website](https://true-myth.dev)
- [README](https://github.com/true-myth/true-myth/blob/main/README.md)
- [Releases](https://github.com/true-myth/true-myth/releases)
- [true-myth/true-myth on GitHub](https://github.com/true-myth/true-myth)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/true-myth-true-myth
