CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-ts-essentials

All essential TypeScript types in one place providing 70+ utility types and helper functions.

Pending
Overview
Eval results
Files

array-tuple-types.mddocs/

Array & Tuple Types

Specialized types for working with arrays, tuples, and array-like structures with type safety. These utilities help you manipulate and constrain array types effectively.

Capabilities

AnyArray

Matches Array<Type> or ReadonlyArray<Type> where Type is any by default.

type AnyArray<Type = any> = Array<Type> | ReadonlyArray<Type>;

Usage Example:

import type { AnyArray } from "ts-essentials";

type StringArrays = AnyArray<string>; // Array<string> | ReadonlyArray<string>

function processArray<T>(arr: AnyArray<T>): T[] {
  return Array.from(arr);
}

// Works with both mutable and readonly arrays
processArray([1, 2, 3]); // Array<number>
processArray(["a", "b"] as const); // readonly string[]

ArrayOrSingle

Matches Type or Type[], useful for APIs that accept either a single value or an array.

type ArrayOrSingle<Type> = Type | Type[];

Usage Example:

import type { ArrayOrSingle } from "ts-essentials";

function addTags(tags: ArrayOrSingle<string>): string[] {
  return Array.isArray(tags) ? tags : [tags];
}

// Both calls are valid
addTags("javascript"); // Works with single string
addTags(["javascript", "typescript"]); // Works with array

// API design example
interface SearchOptions {
  query: string;
  categories: ArrayOrSingle<string>;
  sort: ArrayOrSingle<"date" | "relevance">;
}

ReadonlyArrayOrSingle

Matches Type or readonly Type[], similar to ArrayOrSingle but with readonly constraint.

type ReadonlyArrayOrSingle<Type> = Type | readonly Type[];

Usage Example:

import type { ReadonlyArrayOrSingle } from "ts-essentials";

function processReadonlyData<T>(data: ReadonlyArrayOrSingle<T>): readonly T[] {
  return Array.isArray(data) ? data : [data] as const;
}

// Usage with readonly arrays
const result = processReadonlyData(["a", "b"] as const);
// result is readonly string[]

ElementOf

Constructs a type which equals to array element type for type Type.

type ElementOf<Type> = Type extends ReadonlyArray<infer U> ? U : never;

Usage Example:

import type { ElementOf } from "ts-essentials";

type StringArray = string[];
type ArrayElement = ElementOf<StringArray>; // string

type TupleArray = [number, string, boolean];
type TupleElement = ElementOf<TupleArray>; // number | string | boolean

// Useful for generic functions working with array elements
function processElements<T extends ReadonlyArray<any>>(
  arr: T,
  processor: (element: ElementOf<T>) => ElementOf<T>
): T {
  return arr.map(processor) as T;
}

const numbers = [1, 2, 3];
const doubled = processElements(numbers, x => x * 2); // number[]

Head

Constructs a type which equals to first element in type Type.

type Head<Type extends ReadonlyArray<any>> = Type extends readonly [infer H, ...any[]] ? H : never;

Usage Example:

import type { Head } from "ts-essentials";

type Tuple = [string, number, boolean];
type FirstElement = Head<Tuple>; // string

type EmptyTuple = [];
type EmptyHead = Head<EmptyTuple>; // never

// Runtime helper function
function getHead<T extends ReadonlyArray<any>>(arr: T): Head<T> | undefined {
  return arr[0] as Head<T> | undefined;
}

const tuple = ["hello", 42, true] as const;
const head = getHead(tuple); // "hello"

Tail

Constructs a type which equals to elements but first one in type Type.

type Tail<Type extends ReadonlyArray<any>> = Type extends readonly [any, ...infer T] ? T : [];

Usage Example:

import type { Tail } from "ts-essentials";

type Tuple = [string, number, boolean];
type RestElements = Tail<Tuple>; // [number, boolean]

type SingleTuple = [string];
type SingleTail = Tail<SingleTuple>; // []

// Runtime helper function
function getTail<T extends ReadonlyArray<any>>(arr: T): Tail<T> {
  return arr.slice(1) as Tail<T>;
}

const tuple = ["hello", 42, true] as const;
const tail = getTail(tuple); // [42, true]

NonEmptyArray

Matches array with at least one element of type Type.

type NonEmptyArray<Type> = [Type, ...Type[]];

Usage Example:

import type { NonEmptyArray } from "ts-essentials";

function processNonEmptyArray<T>(arr: NonEmptyArray<T>): T {
  return arr[0]; // Safe to access first element
}

// Type-safe functions that require non-empty arrays
function findMax(numbers: NonEmptyArray<number>): number {
  return Math.max(...numbers);
}

// This works
findMax([1, 2, 3]); // OK

// This would cause a compile error:
// findMax([]); // Error: Argument of type '[]' is not assignable

// Type guard for runtime checking
function isNonEmptyArray<T>(arr: T[]): arr is NonEmptyArray<T> {
  return arr.length > 0;
}

function safeProcessArray<T>(arr: T[]): T | undefined {
  if (isNonEmptyArray(arr)) {
    return processNonEmptyArray(arr); // Type-safe!
  }
  return undefined;
}

Tuple

Matches type constraint for tuple with elements of type Type (any by default).

type Tuple<Type = any> = readonly Type[];

Usage Example:

import type { Tuple } from "ts-essentials";

// Generic tuple constraint
function processTuple<T extends Tuple>(tuple: T): T {
  return tuple;
}

// Works with any tuple
processTuple([1, 2, 3] as const);
processTuple(["a", "b"] as const);

// Typed tuple constraint
function processStringTuple<T extends Tuple<string>>(tuple: T): T {
  return tuple;
}

processTuple(["hello", "world"] as const); // OK
// processTuple([1, 2] as const); // Error: not all elements are strings

Advanced Usage

Combine array and tuple utilities for complex operations:

import type { 
  NonEmptyArray, 
  Head, 
  Tail, 
  ElementOf, 
  ArrayOrSingle 
} from "ts-essentials";

// Recursive tuple processing
type ProcessTuple<T extends ReadonlyArray<any>> = T extends NonEmptyArray<any>
  ? [ProcessElement<Head<T>>, ...ProcessTuple<Tail<T>>]
  : [];

type ProcessElement<T> = T extends string ? `processed_${T}` : T;

type Example = ProcessTuple<["hello", "world", 42]>;
// Result: ["processed_hello", "processed_world", 42]

// Safe array operations
function safeArrayOperation<T extends ReadonlyArray<any>>(
  arr: T
): { 
  first: Head<T> | undefined; 
  rest: Tail<T>; 
  elementType: ElementOf<T> | undefined 
} {
  return {
    first: arr[0] as Head<T> | undefined,
    rest: arr.slice(1) as Tail<T>,
    elementType: arr[0] as ElementOf<T> | undefined
  };
}

// Flexible input handling
function flexibleInput<T>(input: ArrayOrSingle<T>): NonEmptyArray<T> | never {
  const arr = Array.isArray(input) ? input : [input];
  if (arr.length === 0) {
    throw new Error("Input cannot be empty");
  }
  return arr as NonEmptyArray<T>;
}

Types

type ReadonlyArray<T> = readonly T[];
type Array<T> = T[];

Install with Tessl CLI

npx tessl i tessl/npm-ts-essentials

docs

array-tuple-types.md

basic-types.md

change-case-types.md

deep-wrapper-types.md

function-types.md

index.md

key-types.md

mark-wrapper-types.md

type-checkers.md

utility-functions.md

utility-types.md

tile.json