Array Flattening (Specified Depth)
Flattens nested arrays with configurable depth, perfect for processing multi-level nested data structures
Implementation
Copy the complete example or adapt its typed interface to your project. Comments are kept inside the snippet so the intent travels with the code.
/**
* Array flattening with configurable depth
* @param arr Array to be flattened
* @param depth Flattening depth (Infinity by default)
* @returns Flattened array
*/
function flattenArray<T>(arr: any[], depth = Infinity): T[] {
return arr.reduce((acc, item) => {
if (Array.isArray(item) && depth > 0) {
acc.push(...flattenArray(item, depth - 1));
} else {
acc.push(item);
}
return acc;
}, [] as T[]);
}
// Usage Example
console.log(flattenArray([1, [2, [3, [4]]]], 2)); // [1, 2, 3, [4]]
console.log(flattenArray([1, [2, [3]]])); // [1, 2, 3]When to use it
Great for processing nested API responses, tree-structured data, or multi-level menu arrays
Review the input assumptions and browser or runtime support before adopting a utility unchanged. Small helpers are easiest to maintain when their contract stays narrow.
Reasoning and trade-offs
How it works
The recursive step visits nested arrays while the remaining depth is positive and appends non-array values to a new result. Infinity keeps the depth from reaching zero, which produces a complete flatten for finite acyclic arrays.
What to watch for
Deep or adversarial nesting can exhaust the call stack, sparse arrays may not retain their holes, and circular arrays never terminate. Confirm whether the native Array.prototype.flat behavior already matches the required compatibility target.
Production use
Use a custom version when the project needs an explicit compatibility layer or wants to teach the recursion. For application code on modern runtimes, native flat is shorter, optimized, and familiar to most maintainers.
Before you ship
- Confirm the input contract with tests that cover empty, invalid, boundary, and representative real-world values before sharing the helper across a codebase.
- Keep the function focused on one responsibility and name any project-specific policy explicitly instead of hiding it inside a generic-looking utility.
- Measure behavior in the browsers or runtime versions your product supports, especially when timing, storage, DOM state, locale, or network access is involved.
- Document the return type, mutation behavior, failure mode, and performance characteristics beside the call site so future maintainers can evaluate changes safely.
- Compare the example with current official platform documentation when it relies on a browser API, language feature, or runtime behavior that may change over time.
- If the helper crosses a trust boundary, validate again on the server and avoid treating browser-side checks, TypeScript annotations, or formatted output as a security guarantee.
- Add a small regression test whenever a real edge case is discovered; concrete examples preserve the reason behind a guard more reliably than a general comment.