Fast TypeScript (Code Complexity) Analyzer
7 comments
·October 25, 2025austin-cheney
That looks cool. I have never been a fan of cyclomatic complexity analysis. At some point I suspect a perfect score would be branchless code, but that isn’t maintainable.
I prefer redundancy analysis checking for duplicate logic in the code base. It’s more challenging than it sounds.
motorest
> At some point I suspect a perfect score would be branchless code, but that isn’t maintainable.
That's a failure to understand and interpret computational complexity in general, and cyclomatic complexity in particular. I'll explain why.
Complexity is inherent to a problem domain, which automatically means it's unrealistic to assume there's always a no-branching implementation. However, higher-complexity code is associated with higher likelihood of both having bugs and introducing bugs when introducing changes. Higher-complexity code is also harder to test.
Based on this alone, it's obvious that is desirable to produce code with low complexity, and there are advantages in refactoring code to lower it's complexity.
How do you tell if code is complex, and what approaches have lower complexity? You need complexity metrics.
Cyclomatic complexity is a complexity metric which is designed to output a complexity score based on a objective and very precise set of rules: the number of branching operations and independent code paths in a component. The fewer code paths, the easier it is to reason about and test, and harder to hide bugs.
You use cyclomatic complexity to figure out which components are more error-prone and harder to maintain. The higher the score, the higher the priority to test, refactor, and simplify. If you have two competing implementations, In general you are better off adopting the one with the lower complexity.
Indirectly, cyclomatic complexity also offers you guidelines on how wo write code. Branching increases the likelihood of bugs and makes components harder to test and maintain. Therefore, you are better off favoring solutions that minimize branching.
The goal is not to minimize cyclomatic complexity. The goal is to use cyclomatic complexity to raise awareness on code quality problems and drive your development effort. It's something you can automate, too, so you can have it side by side with code coverage. You use the metric to inform your effort, but the metric is not the goal.
devjab
Maybe I'm doing things wrong, but I assume this tool is meant to focus on cognetive complexity and not things like code quality, transpiling or performance, but if that's true then why does this:
(score is 7) function get_first_user(data) { first_user = data[0]; return first_user; }
Score better than this:
(score is 8) function get_first_user(data: User[]): Result<User> { first_user = data[0]; return first_user; }
I mean, I know that the type annotations is what gives the lower score, but I would argue that the latter has the lower cognetive complexity.
uallo
I get the same overall FTA score of 7 for both of your examples. When omitting the return type (which can be inferred), you get the exact same scores. Not just the same FTA score. Also note that `Return<User>` should be just `User` if you prefer to specify the return type explicitly. That change will improve several of the scores as well.
k__
Maybe because the type can be inferred and it potentially adds effort for changes in the future.
zenmac
Then why use TypeScript at all? Just write js and put a TS definition on top. TS is a linter anyway. Now that will make the code easier to read, and in the end it is the code that will be interpreated by the browser or whatever JS runtimes.
For a refactoring project I've built the reports of the tool into the CI pipeline of our repository. On every PR it will create a fixed post with the current branches complexity scores comparing it to the target branch and reporting a trend.
It may not be perfect in its outputs but I like it for bringing attention to arising (or still existing) hotspots.
I've found that the output is - at least on a high level - aligning well with my inner expectation of what files deserve work and which ones are fine. Additionally it's given us measurable outcomes for code refactoring which non technical people like as well.