CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-solid-primitives--utils

A bunch of reactive utility types and functions, for building primitives with Solid.js

Pending
Overview
Eval results
Files

type-definitions.mddocs/

Type Definitions

Comprehensive TypeScript type utilities and definitions for enhanced type safety and developer experience. These types provide powerful abstractions for building type-safe applications with Solid.js and general TypeScript development.

Capabilities

Basic Utility Types

Fundamental type utilities for common programming patterns.

/**
 * Can be single or in an array
 */
type Many<T> = T | T[];

/**
 * Get the values of an object type
 */
type Values<O extends Object> = O[keyof O];

/**
 * Infers the type of the array elements
 */
type ItemsOf<T> = T extends (infer E)[] ? E : never;

/**
 * Element type of Many<T>
 */
type ItemsOfMany<T> = T extends any[] ? ItemsOf<T> : T;

/**
 * No operation function type
 */
type Noop = (...a: any[]) => void;

Usage Examples:

import type { Many, Values, ItemsOf, ItemsOfMany } from "@solid-primitives/utils";

// Many type - accepts single value or array
const acceptMany = (input: Many<string>) => {
  // Handle both "hello" and ["hello", "world"]
};

// Extract array element types
type StringArray = string[];
type ElementType = ItemsOf<StringArray>; // string

// Extract values from object
type User = { id: number; name: string; active: boolean };
type UserValues = Values<User>; // number | string | boolean

Reactive Types

Types specifically designed for reactive programming and Solid.js integration.

/**
 * T or a reactive/non-reactive function returning T
 */
type MaybeAccessor<T> = T | Accessor<T>;

/**
 * Accessed value of a MaybeAccessor
 */
type MaybeAccessorValue<T extends MaybeAccessor<any>> = T extends () => any ? ReturnType<T> : T;

/**
 * Solid.js Setter parameter type
 */
type SetterParam<T> = Parameters<Setter<T>>[0];

/**
 * Directive type for Solid.js
 */
type Directive<P = true> = (el: Element, props: Accessor<P>) => void;

/**
 * Effect function type for reactive computations
 */
type OnAccessEffectFunction<S, Prev, Next extends Prev = Prev> = (
  input: AccessReturnTypes<S>,
  prevInput: AccessReturnTypes<S>,
  v: Prev
) => Next;

/**
 * Return types of accessed values
 */
type AccessReturnTypes<S> = S extends MaybeAccessor<any>[]
  ? { [I in keyof S]: AccessReturnTypes<S[I]>; }
  : MaybeAccessorValue<S>;

Usage Examples:

import { createSignal } from "solid-js";
import type { MaybeAccessor, MaybeAccessorValue, Directive } from "@solid-primitives/utils";

// Function that accepts either value or accessor
const processValue = <T>(input: MaybeAccessor<T>): MaybeAccessorValue<T> => {
  return typeof input === "function" ? input() : input;
};

// Custom directive type
const clickOutside: Directive<() => void> = (el, accessor) => {
  const handler = (e: Event) => {
    if (!el.contains(e.target as Node)) {
      accessor()();
    }
  };
  document.addEventListener("click", handler);
  // ... cleanup logic
};

Object Manipulation Types

Types for safe object manipulation and property access.

/**
 * Allows to make shallow overwrites to an interface
 */
type Modify<T, R> = Omit<T, keyof R> & R;

/**
 * Allows to make nested overwrites to an interface
 */
type ModifyDeep<A extends AnyObject, B extends DeepPartialAny<A>> = {
  [K in keyof A]: B[K] extends never
    ? A[K]
    : B[K] extends AnyObject
      ? ModifyDeep<A[K], B[K]>
      : B[K];
} & (A extends AnyObject ? Omit<B, keyof A> : A);

/**
 * Makes each property optional and turns each leaf property into any, allowing for type overrides
 */
type DeepPartialAny<T> = {
  [P in keyof T]?: T[P] extends AnyObject ? DeepPartialAny<T[P]> : any;
};

/**
 * Get the required keys of an object
 */
type RequiredKeys<T> = keyof {
  [K in keyof T as T extends { [_ in K]: unknown } ? K : never]: 0;
};

Usage Examples:

import type { Modify, ModifyDeep, RequiredKeys } from "@solid-primitives/utils";

// Modify interface
interface User {
  id: number;
  name: string;
  email: string;
}

type AdminUser = Modify<User, { role: "admin"; permissions: string[] }>;
// Result: { id: number; name: string; email: string; role: "admin"; permissions: string[] }

// Deep modification
interface Config {
  database: { host: string; port: number; };
  api: { timeout: number; retries: number; };
}

type CustomConfig = ModifyDeep<Config, {
  database: { ssl: boolean; };
  api: { version: string; };
}>;

// Required keys extraction
interface PartialUser {
  id: number;
  name?: string;
  email?: string;
}

type Required = RequiredKeys<PartialUser>; // "id"

Advanced Utility Types

Advanced type manipulation utilities for complex scenarios.

/**
 * Remove the first item of a tuple [1, 2, 3, 4] => [2, 3, 4]
 */
type Tail<T extends any[]> = ((...t: T) => void) extends (x: any, ...u: infer U) => void ? U : never;

/**
 * Convert union to intersection: A | B => A & B
 */
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;

/**
 * Extract if possible, otherwise return U
 */
type ExtractIfPossible<T, U> = Extract<T, U> extends never ? U : Extract<T, U>;

/**
 * Removes the [Symbol.iterator] functionality
 */
type NonIterable<T> = T & { [Symbol.iterator]: never };

/**
 * Magic type that prevents inference at usage sites
 */
type NoInfer<T> = [T][T extends any ? 0 : never];

Usage Examples:

import type { Tail, UnionToIntersection, NoInfer } from "@solid-primitives/utils";

// Remove first element from tuple
type OriginalTuple = [string, number, boolean];
type RestTuple = Tail<OriginalTuple>; // [number, boolean]

// Convert union to intersection
type Union = { a: string } | { b: number };
type Intersection = UnionToIntersection<Union>; // { a: string } & { b: number }

// Prevent type inference
const createWithDefault = <T>(value: T, defaultValue: NoInfer<T>): T => {
  return value ?? defaultValue;
};

Value and Primitive Types

Types for working with different categories of values.

/**
 * Basic object types
 */
type AnyObject = Record<PropertyKey, any>;
type AnyStatic = [] | any[] | AnyObject;
type AnyFunction = (...args: any[]) => any;
type AnyClass = abstract new (...args: any) => any;

/**
 * Primitive value types
 */
type PrimitiveValue = PropertyKey | boolean | bigint | null | undefined;

/**
 * Falsy and truthy types
 */
type FalsyValue = false | 0 | "" | null | undefined;
type Truthy<T> = Exclude<T, FalsyValue>;
type Falsy<T> = Extract<T, FalsyValue>;

Usage Examples:

import type { AnyObject, PrimitiveValue, Truthy, Falsy } from "@solid-primitives/utils";

// Generic object handling
const processObject = (obj: AnyObject) => {
  // Handle any object type safely
};

// Filter truthy/falsy values
type MixedArray = (string | null | number | undefined | boolean)[];
type TruthyValues = Truthy<MixedArray[number]>; // string | number | true
type FalsyValues = Falsy<MixedArray[number]>; // null | undefined | false

Geometric and UI Types

Types for representing geometric and user interface concepts.

/**
 * 2D position coordinates
 */
type Position = {
  x: number;
  y: number;
};

/**
 * Rectangular dimensions
 */
type Size = {
  width: number;
  height: number;
};

Usage Examples:

import type { Position, Size } from "@solid-primitives/utils";

// Mouse position tracking
const [mousePos, setMousePos] = createSignal<Position>({ x: 0, y: 0 });

// Element dimensions
const [elementSize, setElementSize] = createSignal<Size>({ width: 0, height: 0 });

// Combined for element bounds
type Bounds = Position & Size;
const elementBounds: Bounds = {
  x: 10,
  y: 20,
  width: 100,
  height: 50
};

Type Simplification

Types for improving type readability and unwrapping complex types.

/**
 * Unwraps the type definition of an object, making it more readable
 */
type Simplify<T> = T extends object ? { [K in keyof T]: T[K] } : T;

/**
 * Unboxes type definition, making it more readable
 */
type UnboxLazy<T> = T extends () => infer U ? U : T;

/**
 * Narrow type for better inference
 */
type Narrow<T> = T extends [] ? T : RawNarrow<T>;

type RawNarrow<T> =
  | (T extends [] ? [] : never)
  | (T extends string | number | bigint | boolean ? T : never)
  | { [K in keyof T]: T[K] extends Function ? T[K] : RawNarrow<T[K]> };

Usage Examples:

import type { Simplify, UnboxLazy, Narrow } from "@solid-primitives/utils";

// Simplify complex intersection types
type ComplexType = { a: string } & { b: number } & { c: boolean };
type SimpleType = Simplify<ComplexType>; // { a: string; b: number; c: boolean; }

// Unbox lazy types
type LazyString = () => string;
type UnboxedString = UnboxLazy<LazyString>; // string

// Better type narrowing
const narrowed = <T>(value: T): Narrow<T> => value as any;
const result = narrowed({ a: 1, b: "hello" }); // Properly narrowed type

Re-exported Types

The package also re-exports some useful types from Solid.js:

// From solid-js
type EffectOptions = import("solid-js").EffectOptions;
type OnOptions = import("solid-js").OnOptions;

// Deprecated - from solid-js/types/reactive/signal.js  
type ResolvedJSXElement = import("solid-js/types/reactive/signal.js").ResolvedJSXElement;
type ResolvedChildren = import("solid-js/types/reactive/signal.js").ResolvedChildren;

External Types (from solid-js)

Types from Solid.js that are referenced throughout the API:

/**
 * Solid.js reactive accessor function
 */
type Accessor<T> = () => T;

/**
 * Solid.js reactive setter function
 */
type Setter<T> = (value: T | ((prev: T) => T)) => T;

/**
 * Options for createSignal
 */
interface SignalOptions<T> {
  equals?: false | ((prev: T, next: T) => boolean);
  internal?: boolean;
}

/**
 * Array of accessor functions
 */
type AccessorArray<T> = readonly Accessor<T>[];

/**
 * Effect function type
 */
type EffectFunction<Prev, Next = Prev> = (v: Prev) => Next;

/**
 * Function that returns void
 */
type VoidFunction = () => void;

Install with Tessl CLI

npx tessl i tessl/npm-solid-primitives--utils

docs

environment-utilities.md

immutable-arrays.md

immutable-objects.md

index.md

math-operations.md

reactive-utilities.md

type-definitions.md

tile.json