— No reviews yet
0 installs
10 views
0.0% view→install
Install
$ agentstack add skill-versoxbt-claude-initial-setup-immutability-patterns ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Are you the author of Immutability Patterns? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claimAbout
Immutability Patterns
Create new objects instead of mutating existing ones. Immutability prevents shared-state bugs, makes code easier to reason about, and enables reliable change detection.
When to Use
- Writing any function that transforms data
- Updating React/Vue/Svelte state
- Working with Redux or other state management
- Reviewing code that modifies objects or arrays in place
- Any time
.push(),.splice(),delete, or direct property assignment appears on shared data
Core Patterns
JavaScript/TypeScript: Object Updates
// WRONG: Mutation
function updateUser(user: User, name: string): User {
user.name = name; // Mutates the original!
return user;
}
// CORRECT: Spread operator
function updateUser(user: User, name: string): User {
return { ...user, name };
}
// CORRECT: Nested object update
function updateAddress(user: User, city: string): User {
return {
...user,
address: {
...user.address,
city,
},
};
}
// CORRECT: Conditional field update
function toggleAdmin(user: User): User {
return {
...user,
role: user.role === "admin" ? "user" : "admin",
};
}
JavaScript/TypeScript: Array Operations
// WRONG: Mutating arrays
function addItem(items: Item[], item: Item): Item[] {
items.push(item); // Mutates!
return items;
}
// CORRECT: Immutable array operations
const added = [...items, newItem]; // append
const prepended = [newItem, ...items]; // prepend
const removed = items.filter((item) => item.id !== id); // remove
const updated = items.map((item) => // update
item.id === id ? { ...item, name: "new" } : item
);
const inserted = [ // insert at index
...items.slice(0, index),
newItem,
...items.slice(index),
];
TypeScript: Readonly Types
// Mark data as immutable at the type level
interface Config {
readonly apiUrl: string;
readonly timeout: number;
readonly retries: number;
}
// Readonly arrays
function processItems(items: readonly Item[]): readonly Item[] {
// items.push(x) -> TypeScript error!
return items.filter((item) => item.active);
}
// Deep readonly utility
type DeepReadonly = {
readonly [K in keyof T]: T[K] extends object ? DeepReadonly : T[K];
};
// Readonly records
const routes: Readonly> = {
home: "/",
login: "/auth/login",
dashboard: "/app/dashboard",
};
Deep Cloning and Complex Updates
// structuredClone for deep copies (no functions or symbols)
const copy = structuredClone(complexObject);
// Object.freeze for shallow immutability (runtime enforcement)
const config = Object.freeze({
api: "https://api.example.com",
timeout: 5000,
});
// config.timeout = 3000; -> throws in strict mode, silent in sloppy mode
// For complex nested updates, use a library like immer
import { produce } from "immer";
const nextState = produce(state, (draft) => {
draft.users[0].address.city = "New York"; // Looks like mutation
draft.items.push(newItem); // but produces a new object
});
Python: Immutable Patterns
from dataclasses import dataclass, replace
from typing import NamedTuple
# Use frozen dataclasses
@dataclass(frozen=True)
class User:
name: str
email: str
role: str = "user"
# Create updated copy with replace()
user = User(name="Alice", email="alice@example.com")
updated = replace(user, role="admin") # New object, original unchanged
# Use tuples instead of lists for fixed collections
ALLOWED_ROLES = ("admin", "user", "viewer")
# Use frozenset for immutable sets
VALID_STATUSES = frozenset({"active", "inactive", "pending"})
# NamedTuple for immutable records
class Point(NamedTuple):
x: float
y: float
# Dict updates without mutation
original = {"a": 1, "b": 2}
updated = {**original, "b": 3, "c": 4} # New dict
Go: Immutable Patterns
// Return new structs instead of modifying pointers
type User struct {
Name string
Email string
Role string
}
// WRONG: Mutation via pointer
func (u *User) SetRole(role string) {
u.Role = role
}
// CORRECT: Return new value
func (u User) WithRole(role string) User {
u.Role = role // Modifying the copy (value receiver)
return u
}
// Immutable slice operations
func appendItem(items []Item, item Item) []Item {
result := make([]Item, len(items)+1)
copy(result, items)
result[len(items)] = item
return result
}
func removeItem(items []Item, index int) []Item {
result := make([]Item, 0, len(items)-1)
result = append(result, items[:index]...)
result = append(result, items[index+1:]...)
return result
}
Anti-Patterns
What NOT to Do
- Direct property assignment on shared objects:
user.name = "new"— always spread into a new object. - Array mutators on shared arrays:
.push(),.pop(),.splice(),.sort(),.reverse()— use immutable alternatives or call on a copy. - Assuming Object.freeze is deep: It only freezes the top level. Nested objects are still mutable.
- Over-cloning: Do not
structuredCloneon every operation — use spread for shallow updates, deep clone only when needed.
// BAD: Sorting mutates the original array
const sorted = items.sort((a, b) => a.name.localeCompare(b.name));
// GOOD: toSorted (ES2023) or spread + sort
const sorted = items.toSorted((a, b) => a.name.localeCompare(b.name));
const sorted = [...items].sort((a, b) => a.name.localeCompare(b.name));
// BAD: Reversing mutates
const reversed = items.reverse();
// GOOD: toReversed (ES2023) or spread + reverse
const reversed = items.toReversed();
const reversed = [...items].reverse();
Quick Reference
JavaScript/TypeScript Immutable Operations:
Object update: { ...obj, key: value }
Array append: [...arr, item]
Array remove: arr.filter(x => x.id !== id)
Array update: arr.map(x => x.id === id ? { ...x, ...changes } : x)
Array sort: arr.toSorted(fn) or [...arr].sort(fn)
Array reverse: arr.toReversed() or [...arr].reverse()
Deep clone: structuredClone(obj)
Nested update: immer produce()
TypeScript Types:
readonly prop Readonly ReadonlyArray as const
Python:
@dataclass(frozen=True) replace(obj, field=val)
tuple() frozenset() {**dict, key: val}
Go:
Value receivers Return new structs copy() for slices
Mutating Methods to AVOID (on shared data):
.push() .pop() .shift() .unshift() .splice()
.sort() .reverse() .fill() delete obj.key
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: VersoXBT
- Source: VersoXBT/claude-initial-setup
- License: MIT
- Homepage: https://github.com/VersoXBT/claude-initial-setup#installation
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.