Part of the job is to know when to call it quits and refactor, there's no hard rule. In most cases I'll take a 130 line procedure with three flags that don't heavily interact with each other over three almost-identical 100 line functions.
In languages with good support for functional features, you can curry and compose functions to your heart's content, allowing you to reuse similar logic and take better advantage of type systems like TypeScript's
But well, usually dynamicizing statically-known types yields premature abstraction