Browse packages

Package · v0.18.0

type

Standard library types

TypeScript utility types for JavaScript runtimes.

What is @rcompat/type?#

A collection of TypeScript utility types for type-level programming. Includes type predicates, transformations, and common type aliases. Works consistently across Node, Deno, and Bun.

Installation#

bash
npm install @rcompat/type
bash
pnpm add @rcompat/type
bash
yarn add @rcompat/type
bash
bun add @rcompat/type

Usage#

Basic types#

ts
import type { Dict, Maybe, Nullish, Primitive } from "@rcompat/type";

// Dict<V> = Record<string, V>
const config: Dict<string> = { host: "localhost", port: "3000" };

// Maybe<T> = T | undefined
function find(id: number): Maybe<User> {
  return users.get(id);
}

// Nullish = null | undefined
function isNullish(value: unknown): value is Nullish {
  return value == null;
}

// Primitive = bigint | boolean | null | number | string | symbol | undefined
function isPrimitive(value: unknown): value is Primitive {
  return value !== Object(value);
}

Type predicates#

ts
import type { IsAny, IsNever, IsUnion, IsTuple, IsArray } from "@rcompat/type";

// check if type is `any`
type A = IsAny<any>; // true
type B = IsAny<string>; // false

// check if type is `never`
type C = IsNever<never>; // true
type D = IsNever<void>; // false

// check if type is a union
type E = IsUnion<string | number>; // true
type F = IsUnion<string>; // false

// check if type is a tuple
type G = IsTuple<[string, number]>; // true
type H = IsTuple<string[]>; // false

// check if type is a non-tuple array
type I = IsArray<string[]>; // true
type J = IsArray<[string]>; // false

Type transformations#

ts
import type {
  Mutable,
  DeepMutable,
  Not,
  UnionToTuple,
  TupleToUnion,
} from "@rcompat/type";

// remove readonly modifier
type Writable = Mutable<Readonly<{ a: string }>>;
// { a: string }

// recursively remove readonly
type DeepWritable = DeepMutable<
  Readonly<{ nested: Readonly<{ value: number }> }>
>;
// { nested: { value: number } }

// boolean negation
type Yes = Not<false>; // true
type No = Not<true>; // false

// convert union to tuple
type Tuple = UnionToTuple<"a" | "b" | "c">;
// Contains "a", "b", and "c"; union ordering is compiler-dependent.

// convert tuple to union
type Union = TupleToUnion<["a", "b", "c"]>;
// "a" | "b" | "c"

Function types#

ts
import type { Newable, UnknownFunction } from "@rcompat/type";

// constructor type
function createInstance<T>(Ctor: Newable<T>): T {
  return new Ctor();
}

// generic function signature
function wrap(fn: UnknownFunction) {
   return (...args: unknown[]) => fn(...args);
}

JSON types#

ts
import type { JSONValue, Serializable } from "@rcompat/type";

// valid JSON value
const data: JSONValue = {
  name: "Bob",
  age: 30,
  active: true,
  tags: ["admin", "user"],
};

// implement custom serialization
class User implements Serializable {
  constructor(private id: number, private name: string) {}

  toJSON(): JSONValue {
    return { id: this.id, name: this.name };
  }
}

Async types#

ts
import type { MaybePromise } from "@rcompat/type";

// value or Promise of value
async function process(input: MaybePromise<string>): Promise<string> {
  const value = await input;
  return value.toUpperCase();
}

process("hello"); // works
process(Promise.resolve("hello")); // also works

API Reference#

Basic Types#

Type Definition
Dict<V> Record<string, V>
PartialDict<V> Partial<Record<string, V>>
EmptyDict The inferred type of an empty object literal
Maybe<T> T | undefined
Nullish null | undefined
Primitive bigint | boolean | null | number | string | symbol | undefined
Boolish "true" | "false"
Some<T> true if any element in boolean tuple is true

Type Predicates#

Type Returns true when...
IsAny<T> T is any
IsNever<T> T is never
IsUnknown<T> T is unknown
IsVoid<T> T is void
IsUnion<T> T is a union type
IsArray<T> T is a non-tuple array type
IsTuple<T> T is a tuple type
IsClass<T> T is a non-static object type

Transformations#

Type Description
Mutable<T> Remove readonly modifier
DeepMutable<T> Recursively remove readonly
Not<T> Boolean negation (true ↔ false)
UnionToTuple<U> Convert union to tuple type
TupleToUnion<T> Convert tuple to union type
UndefinedToOptional<T> Make undefined properties optional
LooseOptional<T> Make undefined properties optional while retaining explicit undefined
ImpliedOptional<T> Add undefined when all object properties accept it
Unpack<T> Flatten/expand type for better display

Function Types#

Type Definition
Newable<I, A> new (...args: A) => I
AbstractNewable<I, A> Abstract constructor type
UnknownFunction Any callable function with an unknown result

JSON & Serialization#

Type Description
JSONValue Valid JSON types (primitives, arrays, objects)
Serializable Interface with toJSON(): JSONValue method
JSONPointer JSON pointer path type

Async Types#

Type Definition
MaybePromise<T> T | Promise<T>

Special Types#

Type Description
Print<T> Convert type to string literal representation
TypedArray<Buffer> Union of all typed arrays, optionally restricted by backing buffer
Join<T, D> Join string tuple with delimiter
StringLike string | { toString(): string }
StringClass Interface for string-like classes
Printable Interface with a readonly string Name
PrintableGeneric<T> Printable with a readonly Type marker
Import Module namespace with a default export
UnknownMap Map<PropertyKey, unknown>
UnknownSet Set<unknown>
StringReplacer Replacement callback accepted by String.replace

Join<T, D> uses the delimiter exactly as supplied. Its default delimiter is ", ", which keeps tuple and union printing readable.

Contracts and Platform Types#

Type Description
Bag<V> Readable key/value bag contract
Schema<T> Parser contract from unknown to T
Arch Supported architecture names
OS Supported operating-system names
PackageJSON Package manifest shape
IndexedKeys<T> Whether T exposes string or numeric keys

Examples#

Type-safe event emitter#

ts
import type { Dict, UnknownFunction } from "@rcompat/type";

type Events = Dict<UnknownFunction[]>;

class Emitter<E extends Events> {
  #events: Partial<E> = {};

  on<K extends keyof E>(event: K, handler: E[K][number]) {
     (this.#events[event] ??= [] as E[K]).push(handler);
  }
}

Conditional type utilities#

ts
import type { IsUnion, UnionToTuple } from "@rcompat/type";

type UnionLength<U> = UnionToTuple<U>["length"];

type A = UnionLength<"a" | "b" | "c">; // 3
type B = UnionLength<string>; // 1

JSON validation#

ts
import type { JSONValue } from "@rcompat/type";

function parseJSON(text: string): JSONValue {
  return JSON.parse(text);
}

function stringify(value: JSONValue): string {
  return JSON.stringify(value);
}

Optional undefined properties#

ts
import type { UndefinedToOptional } from "@rcompat/type";

type Input = {
  required: string;
  optional: string | undefined;
};

type Output = UndefinedToOptional<Input>;
// { required: string; optional?: string }

Cross-Runtime Compatibility#

Runtime Supported
Node.js ✓
Deno ✓
Bun ✓
Browser ✓

No configuration required — just import and use.

License#

MIT

Contributing#

See CONTRIBUTING.md in the repository root.