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/typebash
pnpm add @rcompat/typebash
yarn add @rcompat/typebash
bun add @rcompat/typeUsage#
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]>; // falseType 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 worksAPI 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>; // 1JSON 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.