TypeScript’s type system is supposed to make code safer. Yet across 44 open-source repositories, I found structural antipatterns in nearly every single one. The most common issue wasn’t type coverage—it was functions with too many exit points, present in 86% of repositories analyzed.
Methodology
I ran static analysis on 44 public TypeScript repositories, calculating an activity risk score that combines structural complexity (cyclomatic complexity × nesting depth × fan-out) with recent commit frequency. Functions that are both complex and actively changing score highest. Git history from the past 90 days informed the temporal component.
The Most Common Antipatterns
Three patterns dominated the dataset. Exit-heavy functions and god functions each appeared in 38 of 44 repositories (86%)—not a coincidence. They’re symptoms of the same underlying issue: functions that grew beyond their original scope without being decomposed.
Exit-heavy functions scatter responsibility across multiple return statements, making it harder to trace execution flow. In TypeScript specifically, this pattern often emerges from exhaustive type narrowing, where developers add early returns for each discriminated union variant rather than extracting handlers. The type system encourages this—narrowing via control flow is idiomatic—but the result is functions with six, eight, or twelve exit points.
God functions combine high cyclomatic complexity with broad fan-out and excessive length. They become local points of failure: hard to test, hard to modify, and hard to reason about. Complex branching followed at 84% (37 repositories), and deeply nested functions at 80% (35 repositories). The co-occurrence suggests a common evolution path: a function starts simple, gains conditional logic for edge cases, and eventually becomes a nested, branching god function with exits scattered throughout.
The Highest-Risk Repositories
cypress-io/cypress recorded the highest top risk score at 29.4. The repository exhibits cyclic hub patterns alongside complex branching and exit-heavy functions—a combination that makes isolated testing difficult and amplifies the cost of changes.
chatboxai/chatbox and colinhacks/zod tied at 21.3. Both show the same pattern signature: complex branching, deep nesting, and exit-heavy functions. For Zod, this reflects the inherent complexity of schema validation logic—validation libraries must handle numerous input shapes, and that complexity has to live somewhere.
FlowiseAI/Flowise scored 21.2 with identical patterns. AI workflow orchestration involves many conditional paths, and the codebase reflects that domain complexity.
janhq/jan rounds out the top five at 20.7. Jan is a local AI desktop app, and its risk profile reflects the challenge of building cross-platform desktop software: deep conditionals for OS-specific paths, god functions managing model lifecycle, and the churn that comes with a fast-moving product.
What This Means for TypeScript Developers
The data points to a specific intervention: monitor function exit points as aggressively as you monitor function length. TypeScript’s control flow analysis makes early returns attractive for type narrowing, but each return is a potential point where logic can diverge unexpectedly. When a function exceeds four or five exit points, consider whether the branches represent distinct responsibilities that should be separate functions.
The prevalence of god functions (86%) suggests that code review practices aren’t catching complexity accumulation early enough. By the time a function qualifies as a god function, it’s already expensive to refactor. Automated complexity checks in CI—failing builds when cyclomatic complexity exceeds a threshold—can catch these before they calcify.
Analyze Your Own Repository
You can run the same analysis on any local repository. Install the CLI:
brew install Stephen-Collins-tech/tap/hotspots
Or on any platform:
cargo install hotspots-cli
Then run:
hotspots analyze .
The output will surface your highest-risk functions ranked by activity risk, with the specific antipatterns flagged for each.