Getting started
This library brings Rust's Result and Option types to TypeScript with full type safety. This page first covers setup, then introduces both types through small examples.
Installation
bun add results-ts
# or
npm install results-ts
# or
pnpm add results-ts
# or
deno add results-ts
# or
yarn add results-tsBrowser without a bundler
This library is an ES module. To use it directly in a browser, import it from a CDN inside a <script type="module">:
IMPORTANT
The type="module" attribute is required.
<script type="module">
import { Ok } from 'https://unpkg.com/results-ts/dist/index.js';
console.log(
Ok(1)
.map((x) => x + 1)
.unwrap()
); // 2
</script>Core concepts
Use Result when an operation can fail with a useful error. Use Option when a value may be absent and no error details are needed. Both types make each possible outcome explicit, without exceptions or repeated null checks.
Result
Result<T, E> represents either a success (Ok) carrying a value of type T, or a failure (Err) carrying an error of type E. Use it instead of throwing when failures are expected and recoverable.
import { Ok, Err } from 'results-ts';
const parseUserId = (id: string) => {
const parsed = parseInt(id, 10);
if (isNaN(parsed))
return Err({
code: 'INVALID_INPUT',
message: 'ID must be a valid number'
} as const);
if (parsed <= 0)
return Err({
code: 'INVALID_ID',
message: 'ID must be positive'
} as const);
return Ok(parsed);
};
const fetchUser = (id: number) => {
if (id === 13)
return Err({ code: 'NOT_FOUND', message: 'User not found' } as const);
return Ok({ id, name: 'Alice', role: 'admin' });
};
const message = parseUserId('10')
.map((id) => id + 3)
.andThen(fetchUser)
.match({
Ok: (user) => `Welcome, ${user.role} ${user.name}!`,
Err: (error) => {
if (error.code === 'NOT_FOUND')
return `Database Error: ${error.message}`;
return `Validation Error: ${error.message}`;
}
});NOTE
Methods like Result.unwrap(), Result.expect(), Result.unwrapErr(), and Result.expectErr() intentionally panic to mirror Rust. See the Error handling guide for the full story - and prefer Result.unwrapOr(), Result.unwrapOrElse(), or Result.match() when the failure case is recoverable.
Option
Option<T> represents either the presence of a value (Some) or its absence (None). Use it instead of null / undefined checks.
import { Some, None } from 'results-ts';
const parseNickname = (nickname?: string) => {
if (!nickname) return None();
const trimmed = nickname.trim();
return trimmed.length > 0 ? Some(trimmed) : None();
};
const displayName = parseNickname(' Ada ')
.map((name) => name.toUpperCase())
.match({
Some: (name) => name,
None: () => 'ANONYMOUS'
});Note that None is a function - always call it as None() (optionally typed, e.g. None<number>()). Convert an Option back to a Result with Option.okOr(err) or Option.okOrElse(() => err).
Next steps
- Error handling guide - panics, misuse errors, and
catchUnwind. - Async guide - working with
AsyncResultandAsyncOption. - API reference - every type and method, generated from the source.