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

immutable-objects.mddocs/

Immutable Objects

Non-mutating object manipulation functions for property selection, modification, and merging operations. These utilities enable functional programming patterns while maintaining type safety and are ideal for updating Solid.js signals containing object state.

Capabilities

Property Selection

Functions for creating new objects with selected or excluded properties.

/**
 * Create a new subset object without the provided keys
 * @param object - Original object
 * @param keys - Keys to exclude
 * @returns New object without specified keys
 */
function omit<O extends object, K extends keyof O>(object: O, ...keys: K[]): Omit<O, K>;

/**
 * Create a new subset object with only the provided keys
 * @param object - Original object
 * @param keys - Keys to include
 * @returns New object with only specified keys
 */
function pick<O extends object, K extends keyof O>(object: O, ...keys: K[]): Pick<O, K>;

Usage Examples:

import { omit, pick } from "@solid-primitives/utils/immutable";
import { createSignal } from "solid-js";

const [user, setUser] = createSignal({
  id: 1,
  name: "Alice",
  email: "alice@example.com",
  password: "secret",
  role: "admin"
});

// Remove sensitive data
setUser(current => omit(current, "password")); 
// { id: 1, name: "Alice", email: "alice@example.com", role: "admin" }

// Select only public fields
const publicData = pick(user(), "id", "name");
// { id: 1, name: "Alice" }

Property Access

Functions for accessing nested object properties safely.

/**
 * Get a single property value of an object by specifying a path to it
 */
function get<O extends object, K extends keyof O>(obj: O, key: K): O[K];
function get<O extends object, K1 extends keyof O, K2 extends keyof O[K1]>(
  obj: O,
  k1: K1,
  k2: K2
): O[K1][K2];
function get<
  O extends object,
  K1 extends keyof O,
  K2 extends keyof O[K1],
  K3 extends keyof O[K1][K2]
>(obj: O, k1: K1, k2: K2, k3: K3): O[K1][K2][K3];
function get<
  O extends object,
  K1 extends keyof O,
  K2 extends keyof O[K1],
  K3 extends keyof O[K1][K2],
  K4 extends keyof O[K1][K2][K3]
>(obj: O, k1: K1, k2: K2, k3: K3, k4: K4): O[K1][K2][K3][K4];
function get<
  O extends object,
  K1 extends keyof O,
  K2 extends keyof O[K1],
  K3 extends keyof O[K1][K2],
  K4 extends keyof O[K1][K2][K3],
  K5 extends keyof O[K1][K2][K3][K4]
>(obj: O, k1: K1, k2: K2, k3: K3, k4: K4, k5: K5): O[K1][K2][K3][K4][K5];
function get<
  O extends object,
  K1 extends keyof O,
  K2 extends keyof O[K1],
  K3 extends keyof O[K1][K2],
  K4 extends keyof O[K1][K2][K3],
  K5 extends keyof O[K1][K2][K3][K4],
  K6 extends keyof O[K1][K2][K3][K4][K5]
>(obj: O, k1: K1, k2: K2, k3: K3, k4: K4, k5: K5, k6: K6): O[K1][K2][K3][K4][K5][K6];

Usage Examples:

import { get } from "@solid-primitives/utils/immutable";

const data = {
  user: {
    profile: {
      settings: {
        theme: "dark",
        notifications: true
      }
    }
  }
};

// Deep property access
const theme = get(data, "user", "profile", "settings", "theme"); // "dark"
const notifications = get(data, "user", "profile", "settings", "notifications"); // true

// Single level access
const profile = get(data, "user", "profile");

Property Updates

Functions for updating object properties immutably with support for deep nested updates.

/**
 * Change single value in an object by key. Allows accessing nested objects by passing multiple keys.
 * Performs a shallow copy of each accessed object.
 * @param object - Original source object
 * @param keys - Keys of sequential accessed objects
 * @param setter - Value to set or setter function
 * @returns New object with updated value
 */
function update<O extends object, K extends keyof O, V>(
  object: O,
  key: K,
  setter: UpdateSetter<O, K, V>
): ModifyValue<O, K, V>;

function update<O extends object, K0 extends keyof O, K1 extends keyof O[K0], V>(
  object: O,
  k0: K0,
  k1: K1,
  setter: UpdateSetter<O[K0], K1, V>
): ModifyValue<O, K0, ModifyValue<O[K0], K1, V>>;

function update<
  O extends object,
  K0 extends keyof O,
  K1 extends keyof O[K0],
  K2 extends keyof O[K0][K1],
  V
>(
  object: O,
  k0: K0,
  k1: K1,
  k2: K2,
  setter: UpdateSetter<O[K0][K1], K2, V>
): ModifyValue<O, K0, ModifyValue<O[K0], K1, ModifyValue<O[K0][K1], K2, V>>>;

function update<
  O extends object,
  K0 extends keyof O,
  K1 extends keyof O[K0],
  K2 extends keyof O[K0][K1],
  K3 extends keyof O[K0][K1][K2],
  V
>(
  object: O,
  k0: K0,
  k1: K1,
  k2: K2,
  k3: K3,
  setter: UpdateSetter<O[K0][K1][K2], K3, V>
): ModifyValue<
  O,
  K0,
  ModifyValue<O[K0], K1, ModifyValue<O[K0][K1], K2, ModifyValue<O[K0][K1][K2], K3, V>>>
>;

function update<
  O extends object,
  K0 extends keyof O,
  K1 extends keyof O[K0],
  K2 extends keyof O[K0][K1],
  K3 extends keyof O[K0][K1][K2],
  K4 extends keyof O[K0][K1][K2][K3],
  V
>(
  object: O,
  k0: K0,
  k1: K1,
  k2: K2,
  k3: K3,
  k4: K4,
  setter: UpdateSetter<O[K0][K1][K2][K3], K4, V>
): ModifyValue<
  O,
  K0,
  ModifyValue<
    O[K0],
    K1,
    ModifyValue<O[K0][K1], K2, ModifyValue<O[K0][K1][K2], K3, ModifyValue<O[K0][K1][K2][K3], K4, V>>>
  >
>;

type UpdateSetter<O, K extends keyof O, V> = V | ((prev: O[K]) => V);

Usage Examples:

import { update } from "@solid-primitives/utils/immutable";
import { createSignal } from "solid-js";

const [state, setState] = createSignal({
  user: {
    name: "Alice",
    settings: {
      theme: "light",
      notifications: {
        email: true,
        push: false
      }
    }
  },
  count: 0
});

// Simple update
setState(current => update(current, "count", 1));

// Deep nested update with value
setState(current => update(current, "user", "settings", "theme", "dark"));

// Deep nested update with function
setState(current => update(
  current, 
  "user", "settings", "notifications", "email", 
  prev => !prev
));

// Function-based update
setState(current => update(current, "count", prev => prev + 1));

Object Splitting

Functions for splitting objects into multiple subset objects.

/**
 * Split object properties by keys into multiple object copies with a subset of selected properties
 * @param object - Original object
 * @param keys - Keys to pick from the source, or arrays of keys for multiple splits
 * @returns Array of subset objects
 */
function split<T extends object, K extends keyof T>(
  object: T,
  ...keys: K[]
): [Pick<T, K>, Omit<T, K>];

function split<T extends object, K1 extends keyof T, K2 extends keyof T>(
  object: T,
  ...keys: [K1[], K2[]]
): [Pick<T, K1>, Pick<T, K2>, Omit<T, K1 | K2>];

function split<T extends object, K1 extends keyof T, K2 extends keyof T, K3 extends keyof T>(
  object: T,
  ...keys: [K1[], K2[], K3[]]
): [Pick<T, K1>, Pick<T, K2>, Pick<T, K3>, Omit<T, K1 | K2 | K3>];

Usage Examples:

import { split } from "@solid-primitives/utils/immutable";

const user = {
  id: 1,
  name: "Alice",
  email: "alice@example.com",
  password: "secret",
  role: "admin",
  createdAt: new Date()
};

// Simple split - public vs private
const [publicData, privateData] = split(user, "id", "name", "email");
// publicData: { id: 1, name: "Alice", email: "alice@example.com" }
// privateData: { password: "secret", role: "admin", createdAt: Date }

// Multiple splits
const [identity, security, metadata, rest] = split(
  user,
  ["id", "name"],
  ["password", "role"],
  ["createdAt"]
);
// identity: { id: 1, name: "Alice" }
// security: { password: "secret", role: "admin" }
// metadata: { createdAt: Date }
// rest: { email: "alice@example.com" }

Object Merging

Functions for merging multiple objects into a single object.

/**
 * Merges multiple objects into a single one. Only the first level of properties is merged.
 * An alternative to { ...a, ...b, ...c }
 * @param objects - Objects to merge
 * @returns New merged object
 */
function merge<A extends object, B extends object>(a: A, b: B): Modify<A, B>;
function merge<A extends object, B extends object, C extends object>(
  a: A,
  b: B,
  c: C
): Modify<Modify<A, B>, C>;
function merge<A extends object, B extends object, C extends object, D extends object>(
  a: A,
  b: B,
  c: C,
  d: D
): Modify<Modify<Modify<A, B>, C>, D>;
function merge<
  A extends object,
  B extends object,
  C extends object,
  D extends object,
  E extends object
>(a: A, b: B, c: C, d: D, e: E): Modify<Modify<Modify<Modify<A, B>, C>, D>, E>;
function merge<
  A extends object,
  B extends object,
  C extends object,
  D extends object,
  E extends object,
  F extends object
>(a: A, b: B, c: C, d: D, e: E, f: F): Modify<Modify<Modify<Modify<Modify<A, B>, C>, D>, E>, F>;

Usage Examples:

import { merge } from "@solid-primitives/utils/immutable";

const defaults = { theme: "light", lang: "en" };
const userPrefs = { theme: "dark", fontSize: 14 };
const systemPrefs = { highContrast: false };

const finalPrefs = merge(defaults, userPrefs, systemPrefs);
// { theme: "dark", lang: "en", fontSize: 14, highContrast: false }

Copying Utilities

Functions for creating shallow copies of objects and arrays.

/**
 * Make shallow copy of an array
 * @param array - Array to copy
 * @returns New array with same elements
 */
function shallowArrayCopy<T>(array: readonly T[]): T[];

/**
 * Make shallow copy of an object
 * @param object - Object to copy
 * @returns New object with same properties
 */
function shallowObjectCopy<T extends object>(object: T): T;

/**
 * Make shallow copy of an array/object
 * @param source - Array or object to copy
 * @returns New copy of the source
 */
function shallowCopy<T extends object>(source: T): T;

/**
 * Apply mutations to an array without changing the original
 * @param array - Original array
 * @param mutator - Function that applies mutations to the copy
 * @returns New array with mutations applied
 */
function withArrayCopy<T>(array: readonly T[], mutator: (copy: T[]) => void): T[];

/**
 * Apply mutations to an object without changing the original
 * @param object - Original object
 * @param mutator - Function that applies mutations to the copy
 * @returns New object with mutations applied
 */
function withObjectCopy<T extends object>(object: T, mutator: (copy: T) => void): T;

/**
 * Apply mutations to an object/array without changing the original
 * @param source - Original object or array
 * @param mutator - Function that applies mutations to the copy
 * @returns New copy with mutations applied
 */
function withCopy<T extends object>(source: T, mutator: (copy: T) => void): T;

Usage Examples:

import { 
  shallowArrayCopy, shallowObjectCopy, withArrayCopy, withObjectCopy 
} from "@solid-primitives/utils/immutable";

// Shallow copying
const originalArray = [1, 2, 3];
const copiedArray = shallowArrayCopy(originalArray); // [1, 2, 3]

const originalObject = { a: 1, b: 2 };
const copiedObject = shallowObjectCopy(originalObject); // { a: 1, b: 2 }

// Mutating copies
const numbers = [1, 2, 3];
const reversed = withArrayCopy(numbers, arr => arr.reverse()); // [3, 2, 1]

const user = { name: "Alice", age: 30 };
const updated = withObjectCopy(user, obj => {
  obj.age = 31;
  obj.status = "active";
}); // { name: "Alice", age: 31, status: "active" }

Types

type UpdateSetter<O, K extends keyof O, V> = V | ((prev: O[K]) => V);
type ModifyValue<O, K extends keyof O, V> = Omit<O, K> & { [key in K]: V };
type Modify<T, R> = Omit<T, keyof R> & R;

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