npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

slang-ts

v0.0.1

Published

Functional programming library for TypeScript

Downloads

121

Readme

Slang

Functional programming library for TypeScript.

My experiment to learn more functional programming and other cool programming stuff from other languages as I try to implement them in TypeScript.

Install

npm i slang-ts

Implemented Utilities

  • [x] Result (Ok, Err)
  • [x] Maybe (Option)
  • [ ] andThen
  • [x] Atom
  • [x] Expect
  • [x] Unwrap (on Option)
  • [x] Else (on unwrap)
  • [ ] Panic!
  • [x] Zip, Unzip, zipWith
  • [ ] Try
  • [ ] Catch
  • [x] Match
  • [x] MatchAll
  • [ ] Pipe
  • [ ] Map
  • [x] To (converters, e.g. userAtom.to('option'))
  • [ ] Promises and async utilities
  • [ ] Curry

Others (Planned)

  • Pubsub store with state locks

How It Works

You can import utilities individually or together:

// Individual imports
import { option } from "slang-ts";
import { Ok, Err } from "slang-ts";

// Or import multiple at once
import { option, Ok, Err, atom, match } from "slang-ts";

println

Well there's nothing special to slang's println utility, its just who wants console.log, its not fun at all, so we instead println, clean and classic, but latter it can be made environment aware so it doesn't print in prod, but for now its just sugar for console.log.

import { println } from "slang-ts";

const name = "kizz";
println("name:", name);
println("multiple", "args", "work", { too: true });

Option

Wraps values that may or may not be present. Returns Some<T> for truthy values, None for null, undefined, empty strings, NaN, or Infinity. Note that 0 and false are truthy as these are usually intentional.

import { option } from "slang-ts";

const a = option("hi");      // Some("hi")
const b = option(null);      // None
const c = option(0);         // Some(0) - zero is truthy!
const d = option("");        // None
const e = option(false);     // Some(false) - false is truthy!

if (a.isSome) {
  println("Value:", a.value);
}

if (b.isNone) {
  println("No value");
}

Result

Represents operations that can succeed or fail. Returns Ok<T> on success or Err<E> on failure with typed error payload.

import { Ok, Err, type Result } from "slang-ts";

// Simple function returning Result
function divide(a: number, b: number): Result<number, string> {
  if (b === 0) return Err("Cannot divide by zero");
  return Ok(a / b);
}

const result = divide(10, 2);

if (result.isOk) {
  println("Success:", result.value); // 5
} else {
  println("Error:", result.error);
}

// Async API example
interface User {
  id: string;
  name: string;
}

async function fetchUser(id: string): Promise<Result<User, string>> {
  try {
    const response = await fetch(`/api/users/${id}`);
    if (!response.ok) return Err("User not found");
    const user = await response.json();
    return Ok(user);
  } catch (error) {
    return Err("Network error");
  }
}

const user = await fetchUser("123");
if (user.isOk) {
  println("User:", user.value.name);
}

Atom

Creates unique, non-interned symbols with semantic descriptions. Each call produces a distinct identity. So ideally define them in one file and import from it everywhere else, great for env variables stuff.

import { atom } from "slang-ts";

const userAtom = atom("kizz");
const user2Atom = atom("kizz");

println(userAtom === atom("kizz")); // false - non interned ✅
println(userAtom.description);      // "kizz"

if (userAtom === user2Atom) {
  println("all the same");
} else {
  println("not the same");          // This prints!
}

Match

Exhaustive pattern matching for Option and Result types. Forces you to handle all cases.

import { match } from "slang-ts";

// Matching Results
const result = divide(10, 0);
match(result, {
  Ok: (v) => println("Success:", v.value),
  Err: (e) => println("Failed:", e.error),
});

// Matching Options
const maybePort = option(process.env.PORT);
match(maybePort, {
  Some: (v) => println("Port:", v.value),
  None: () => println("No port configured"),
});

MatchAll

Pattern matching for primitives and atoms with required _ fallback.

import { matchAll } from "slang-ts";

// Match atoms
const ready = atom("ready");
matchAll(ready, {
  ready: () => println("Ready!"),
  failed: () => println("Failed!"),
  _: () => println("Unknown"),
});

// Match booleans
const isActive = true;
matchAll(isActive, {
  true: () => println("Active"),
  false: () => println("Inactive"),
  _: () => println("Unknown"),
});

Expect

Unwraps values or throws with custom message. Use when failure is unrecoverable.

const personAge = option(25).expect("a person must have age!");
println("person age", personAge); // 25

// This would throw!
// const personAge2 = option("").expect("a person must have age!");

Unwrap/Else

Chainable unwrapping with mandatory fallback. Must call .else() or throws.

const port = option(process.env.PORT).unwrap().else(3000);
println("Using port:", port);

// Function fallbacks
const retries = option(null).unwrap().else(() => 5);
println("Retries:", retries);

// This throws! No .else() chained
// const nothing = option(null).unwrap();

To

Converts between Slang types.

const statusAtom = atom("active").to("option");
println("Option:", statusAtom);           // Some("active")

const stateOption = option("ready").to("atom");
println("Atom:", stateOption.description); // "ready"

const errResult = option(null).to("result");
println("Result:", errResult.type);        // "Err"

Zip

Combines multiple collections element-wise into tuples.

import { zip } from "slang-ts";

// Zip arrays
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const arr3 = [7, 8, 9];
println(zip([arr1, arr2, arr3]));
// [[1,4,7],[2,5,8],[3,6,9]]

// Zip with fillValue
println(zip([arr1, [10, 20]], { fillValue: 0 }));
// [[1,10],[2,20],[3,0]]

// Zip Sets with includeValues=true
const s1 = new Set([10, 20, 30]);
const s2 = new Set([100, 200, 300]);
println(zip([s1, s2], { includeValues: true }));
// [[10,100],[20,200],[30,300]]

// Zip objects with includeValues=true
const o1 = { a: 1, b: 2, c: 3 };
const o2 = { x: 100, y: 200, z: 300 };
println(zip([o1, o2], { includeValues: true }));
// [[1,100],[2,200],[3,300]]

ZipWith

Combines collections and applies transform function to each tuple.

import { zipWith } from "slang-ts";

const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const arr3 = [7, 8, 9];

println(zipWith([arr1, arr2, arr3], (t) => t.reduce((sum, x) => sum + x, 0)));
// [12, 15, 18]

Unzip

Reverses zip operation, separating tuples back into arrays.

import { unzip } from "slang-ts";

const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];

const zipped = zip([arr1, arr2]);
println(unzip(zipped));
// [[1, 2, 3], [4, 5, 6]]

And more are to be implemented in coming versions...

Code Samples

See example.ts for usage of currently implemented methods.

Contributing

Contributions are welcome, I know there a lot of cool things out there we can bring in.