sc-fns

Best Practices & Performance

Architectural guidelines, immutability patterns, and bundle optimization techniques when using sc-fns.


1. Always Prefer Subpath Imports in Frontend Bundles

While import { slugify } from "sc-fns" is supported and tree-shakeable, using explicit subpath imports (import { slugify } from "sc-fns/string") offers concrete advantages:

ts
// Recommended for client components & frontend code: import { slugify } from "sc-fns/string"; import { formatNumber } from "sc-fns/number";

2. Embrace Non-Mutating Patterns

All array and object utilities in sc-fns are designed as pure functions. They never mutate arguments in place:

ts
import { shuffleArray, removeItem } from "sc-fns/array"; const state = [1, 2, 3, 4]; // Safe for React state and Redux reducers: const nextState = removeItem(state, 2); console.log(state); // [1, 2, 3, 4] (Unchanged!) console.log(nextState); // [1, 3, 4]

This pattern makes sc-fns ideal for:


3. Leverage TypeScript Return Types and Generics

Functions like pick, omit, and groupBy provide exact TypeScript type contracts:

ts
import { pick } from "sc-fns/object"; interface UserProfile { id: string; name: string; email: string; secretKey: string; } const user: UserProfile = { id: "u_1", name: "Sam", email: "sam@example.com", secretKey: "k_982", }; // Return type is strictly Pick<UserProfile, "id" | "name">: const safeUser = pick(user, ["id", "name"]); // safeUser.email -> Type Error!

4. Debouncing and Throttling in React

When using debounce or throttle inside React components, remember to wrap them with useCallback or useMemo so that new timers are not instantiated on every component render:

tsx
import { useMemo, useEffect } from "react"; import { debounce } from "sc-fns/common"; export function SearchInput({ onSearch }: { onSearch: (val: string) => void }) { const debouncedSearch = useMemo( () => debounce((val: string) => onSearch(val), 300), [onSearch], ); useEffect(() => { return () => debouncedSearch.cancel(); }, [debouncedSearch]); return <input onChange={(e) => debouncedSearch(e.target.value)} />; }

How is this guide?

Last updated on October 25, 2026