README

Variant type implementation for TypeScript.

This package provides two classes “Variant” for a general variants of type: [string, any] and Result for a Result type

Installation

node

npm install variant

deno

import { Variant, Result } from "https://deno.land/x/variant/mod.ts";

Usage

Variant

import { Variant } from "@sel/variant";

type V1 =
  | ["foo", number]
  | ["bar", string];

const v1: V1 = ["foo", 3];

const result = Variant.match<V1, string>(v1, {
  foo(n: number) {
    return "ok" + n;
  },
  bar(s: string) {
    return "ok" + s;
  },
});

const n = Variant.unwrap(v1, "foo");

if (Variant.is(v1, "foo")) {
  const n = Variant.unwrap(v1, "foo"); // "n" is number
  console.log("is foo");
}

Result

import { Result } from "@sel/variant";

const result = Result.ok(3);

const result2 = Result.match(result, {
  ok(n: number) {
    return "ok" + n;
  },
  err(e: Error) {
    return "err" + e.message;
  },
});


const x = Result.ok(2);
const y = Result.map(x, (n) => n * 2);

const z = Result.chain(y)
  .map((n) => n * 2)
  .map((n) => n.toString())
  .mapErr((e) => "otherError")
  .match({
    ok(n) {
      return "ok" + n;
    },
    err(e) {
      return "err" + e;
    },
  });

API

Variant

  • match<V extends VariantBase, R>(val: V, cases: VariantMatch<V, R>): R;

    Match a variant value with a set of cases. Each case must return the same type.

  • unwrap<V extends VariantBase>( val: V, name: V[0],): typeof val extends [V[0], infer A] ? A : never;

    Unwrap a variant value. If the variant value does not match the name, an error is thrown. The return type is inferred from the variant value.

    @throws

  • is<V extends VariantBase>( val: unknown, key: V[1],): val is V extends [V[0], infer A] ? [V[0], A] : never;

    Check if a value is a variant value. Adds a type guard so after checking the compiler will infer the type:

if (Variant.is(v1, "foo")) {
  const n = Variant.unwrap(v1, "foo"); // "n" is number
  console.log("is foo");
}

Result

  • err<Err>(reason: Err): Result<any, Err>;

    Create an “err” Result.

  • ok<Ok>(value: Ok): Result<Ok, any>;

    Create an “ok” Result.

  • chain<Ok, Err>(result: Result<Ok, Err>): Chain<Ok, Err>;

    Creates a “Chain” object that can be used for chaining operations on Result

  • isOk<Ok, Err>(result: Result<Ok, Err>): result is ["ok", Ok];

    Check if a value is a “ok” Result.

  • isErr<Ok, Err>(result: Result<Ok, Err>): result is ["err", Err];

    Check if a value is a “err” Result.

  • map<Ok, Err, NewOk>(result: Result<Ok, Err>, f: (value: Ok) => NewOk): Result<NewOk, Err>;

    Map a Result value to a new value.

  • mapErr<Ok, Err, NewErr>( result: Result<Ok, Err>, f: (reason: Err) => NewErr,): Result<Ok, NewErr>;

    Map a Result error to a new error.

  • unwrap<Ok, Err>(result: Result<Ok, Err>): Ok;

    Unwrap a “ok” Result value. If the Result is “err” then an Error is thrown.

  • match<Ok, Err, Return>(result: Result<Ok, Err>, cases: { ok: (value: Ok) => Return; err: (reason: Err) => Return; }): Return;

    Match a Result value with a set of cases. Each case must return the same type.

  • Chain

Chain is a class for chaining operations on Result.

It’s methods are as follows:

  constructor(private result: Result<Ok, Err>);
  public isOk(): boolean;
  public isErr(): boolean {
  map<NewOk>(f: (value: Ok) => NewOk): Chain<NewOk, Err>;
  mapErr<NewErr>(f: (reason: Err) => NewErr): Chain<Ok, NewErr>;
  unwrap(): Ok;
  match<Return>(cases: { ok: (value: Ok) => Return; err: (reason: Err) => Return; }): Return;