Function
Closure Depth
Maximum function nesting depth — a proxy for callback hell.
What it measures
Closure Depth counts how many function scopes are nested inside one another, starting from 1 for the outermost function. A standalone function has depth 1; a callback inside it has depth 2; a callback inside that has depth 3, and so on.
High closure depth is a classic sign of callback hell — deeply nested asynchronous callbacks that are hard to read, test, and reason about.
How it's computed
tsmetrics walks the AST and increments a depth counter each time it enters a function node (function_declaration, function_expression, arrow_function, or method_definition). The maximum depth seen in the file is reported.
depth(node) = 1 + max(depth(child) for child in function_children(node))
Examples
TypeScript — depth 1 (clean)
function fetchUser(id: string) { return db.query(id); }
TypeScript — depth 4 (callback hell)
function fetchData() { // depth 1 doA(function() { // depth 2 doB(function() { // depth 3 doC(() => { /* … */ }); // depth 4 }); }); }
Tip: Refactor deeply nested callbacks using
async/await, named functions, or Promise chaining. Aim for closure depth ≤ 2.
Interpretation
| Depth | Meaning |
|---|---|
| 1 | Single function — no nesting |
| 2 | One level of callbacks — generally fine |
| 3 | Starting to get complex — consider refactoring |
| 4+ | Callback hell — refactor with async/await or named functions |