Skip to content
cccskills
FreePublished on GitHub

web-utilities-native-js

Modern native JavaScript (ES2022-ES2025) utility patterns that replace lodash

The English summary is being prepared. Showing the original description.

See how to install

Files included (6)

  • SKILL.md8.5 KB
  • examples/arrays.md7.7 KB
  • examples/core.md4.5 KB
  • examples/objects.md5.3 KB
  • metadata.yaml344 B
  • reference.md7.4 KB

SKILL.md (original)

Review the instructions the agent will receive before you install.

Native JavaScript Utility Patterns

Quick Guide: Most utility-library calls now have a native equivalent with no bundle cost. The four that change how code is written are structuredClone for deep copies, the ES2023 immutable array methods (toSorted, toReversed, toSpliced, with), Object.groupBy / Map.groupBy, and the ES2025 Set operations. The two facts that catch people out: a structured clone drops prototypes and throws on functions, and the immutable array methods copy one level deep.

Detailed Resources:

  • examples/core.md — cloning, immutable updates, negative indexing, searching from the end
  • examples/arrays.md — deduplication, set operations, grouping, chunking, sorting, compacting
  • examples/objects.md — typed pick/omit/mapValues, deep merge, lookup maps, freezing
  • reference.md — lodash-to-native table, function utilities (debounce, throttle, memoize), availability

<critical_requirements>

Before writing utility code

Reach for the native method before adding a dependency. The lodash-to-native table in reference.md settles most of it in one lookup, and the native call ships nothing.

Deep-copy with structuredClone. A JSON round trip turns a Date into a string and a Map or Set into {}, and it does so silently — the failure surfaces later, at the first .getTime().

Use the to* array methods where the array is shared. sort, reverse and splice rewrite the array in place, so a function that "returns a sorted copy" with sort has changed its caller's data.

Convert to a Set before repeated membership checks. includes inside a filter is O(n²), and the difference shows up at a few thousand elements.

</critical_requirements>


Auto-detection: structuredClone, Object.groupBy, Map.groupBy, toSorted, toReversed, toSpliced, Array.prototype.with, findLast, findLastIndex, at(-1), Object.hasOwn, Object.fromEntries, Set.prototype.union, Set.prototype.intersection, Set.prototype.difference, symmetricDifference, isSubsetOf, isDisjointFrom, lodash alternative, native JavaScript utilities

Applies to:

  • Array work — deduplicating, grouping, chunking, flattening, sorting immutably, searching from the end
  • Object work — picking, omitting, merging, key/value transformation, lookup maps
  • Set algebra — union, intersection, difference, subset tests
  • Deep copying without a dependency
  • Hand-rolled function utilities — debounce, throttle, memoize, once

Handled elsewhere:

  • Date arithmetic, parsing and formatting — Date alone does not cover it
  • Reactive updates — these methods produce new references, and what consumes a new reference is the concern of whatever owns the state
  • Schema validation and runtime parsing — these utilities reshape data that is already trusted

<decision_framework>

Native or a dependency

Three cases, in order:

  • A native method exists — use it. The table in reference.md is the lookup.
  • No native method, but the implementation is ten lines — write it. chunk, pick, omit, compact, deepMerge, debounce, throttle, memoize and once are all in this skill, written out and typed.
  • The edge cases are the feature — take the dependency. A debounce with cancel, flush and leading/trailing edges; a deep merge with per-key array strategies; lazy evaluation over a dataset large enough that intermediate arrays matter. Reimplementing these badly costs more than the bytes.

</decision_framework>


<patterns>

Core patterns

Pattern 1: structuredClone for deep copies

Preserves Date, Map, Set, RegExp, typed arrays and circular references — everything a JSON round trip destroys.

const snapshot = structuredClone(state);
// Preserved: Date, Map, Set, RegExp, ArrayBuffer, circular refs
// Throws on: functions, DOM nodes, Proxy, symbols
// Silently lost: the prototype — a class instance clones to a plain object

Full code: examples/core.md


Pattern 2: Immutable array methods (ES2023)

Four to* methods return a new array where the classic method rewrote the old one.

items.toSorted((a, b) => a.price - b.price); // vs .sort()
items.toReversed(); // vs .reverse()
items.toSpliced(index, 1); // vs .splice()
items.with(index, { ...items[index], done: true }); // vs items[i] = x

The copy is shallow: the new array holds the same element objects, which is why the update above spreads before writing.

Full code: examples/core.md


Pattern 3: Object.groupBy and Map.groupBy (ES2024)

const byStatus = Object.groupBy(orders, (order) => order.status);
// { pending: [...], shipped: [...] } — null-prototype, values are `T[] | undefined`

const byCustomer = Map.groupBy(orders, (order) => order.customer);
// Map keyed by the object itself — use this when the key is not a string

Object.groupBy coerces the key to a string and returns a null-prototype object, so reach for Object.hasOwn(byStatus, key) rather than byStatus.hasOwnProperty(key).

Full code: examples/arrays.md


Pattern 4: Set operations (ES2025)

setA.union(setB);
setA.intersection(setB);
setA.difference(setB); // in A, not in B
setA.symmetricDifference(setB);
setA.isSubsetOf(setB);
setA.isSupersetOf(setB);
setA.isDisjointFrom(setB);

Each returns a Set, so spread when an array is wanted. The argument is any set-like with size, has and keys — a Map qualifies, a plain array does not.

Full code: examples/arrays.md


Pattern 5: Searching and indexing from the end

logs.findLast((log) => log.level === "error"); // ES2023, single pass
logs.findLastIndex((log) => log.level === "error");
items.at(-1); // ES2022, undefined when empty
"file.backup.txt".split(".").at(-1); // "txt" — strings too

Full code: examples/core.md


Pattern 6: Object.fromEntries as the transformation pivot

entries → map/filter → fromEntries covers pick, omit, invert, mapValues, mapKeys and array-to-lookup in one shape, so those helpers are four lines each rather than a dependency.

const keyed = Object.fromEntries(items.map((item) => [item.id, item]));
const withTax = Object.fromEntries(
  Object.entries(prices).map(([k, v]) => [k, v * 1.1]),
);
const passing = Object.fromEntries(
  Object.entries(scores).filter(([, score]) => score >= 90),
);

Full code: examples/objects.md

</patterns>

<red_flags>

Red flags

Breaks at runtime:

  • structuredClone on anything holding a function, a DOM node or a Proxy throws DataCloneError — clone the data separately from the behaviour.
  • JSON.parse(JSON.stringify(x)) does not throw; it corrupts. A Date becomes a string, a Map or Set becomes {}, undefined members vanish, and the first method call on the result is where it surfaces.
  • Object.groupBy returns a null-prototype object, so result.hasOwnProperty(...) throws. Use Object.hasOwn.
  • Set methods reject a plain array — they need something with size, has and keys.

Surprising behaviour:

  • structuredClone discards the prototype. A class instance clones to a plain object with the same fields and none of the methods.
  • toSorted() with no comparator sorts by string, so [10, 9, 1].toSorted() is [1, 10, 9] — exactly as sort() always did.
  • The to* methods copy one level. Editing an element of the new array edits the same object in the old one.
  • arr.at(-1) types as T | undefined whatever the compiler options, so the empty case has to be handled. arr[arr.length - 1] types as T unless noUncheckedIndexedAccess is on — that is the form that lets an undefined flow on unchecked.
  • structuredClone on an Error succeeds and keeps the standard fields, but a code, a status or anything else attached to it is not in the copy.
  • filter(Boolean) drops 0, "" and false along with the nullish values, and TypeScript does not narrow the result — filter((x): x is T => x != null) does both jobs correctly.
  • Object.freeze is shallow, and outside strict mode a write to a frozen object fails silently rather than throwing.
  • Object.keys returns integer-like keys first in ascending numeric order, whatever the insertion order — only string keys keep insertion order.

</red_flags>

Reviews

No reviews yet. Tell others what you thought.

Comments

No login needed. Share how it worked for you, ask a question, or note where it did not run.

No comments yet. Be the first to write one.

Comments are published right away. Do not include personal information such as email addresses or phone numbers. Up to 2 URLs.

0 / 1,000 characters

This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.

More skills from this repository

Hugging Face Inference SDK patterns for TypeScript/Node.js — InferenceClient setup, chat completion, text generation, streaming, embeddings, image generation, audio transcription, translation, summarization, and Inference Endpoints

The English summary is being prepared. Showing the original description.

agents-inc/skills25Updated Oct 17, 2026

LiteLLM proxy server setup, TypeScript client patterns via OpenAI SDK, model routing, fallbacks, load balancing, spend tracking, virtual keys, and production deployment

The English summary is being prepared. Showing the original description.

agents-inc/skills25Updated Oct 17, 2026

Serverless GPU compute platform for AI model deployment — web endpoints, GPU functions, model serving, and TypeScript client patterns

The English summary is being prepared. Showing the original description.

agents-inc/skills25Updated Oct 17, 2026

Local LLM inference with the Ollama JavaScript client -- chat, streaming, tool calling, vision, embeddings, structured output, model management, and OpenAI-compatible endpoint

The English summary is being prepared. Showing the original description.

agents-inc/skills25Updated Oct 17, 2026

Replicate SDK patterns for TypeScript/Node.js -- client setup, predictions, streaming, webhooks, file handling, model versioning, deployments, and training

The English summary is being prepared. Showing the original description.

agents-inc/skills25Updated Oct 17, 2026

Together AI SDK patterns for TypeScript — client setup, chat completions, streaming, structured output, function calling, embeddings, image generation, fine-tuning, and OpenAI-compatible endpoints

The English summary is being prepared. Showing the original description.

agents-inc/skills25Updated Oct 17, 2026

See all skills by agents-inc

Report a problem with this skill