34

I've been trying to research this but can't see to find any recommendations. I've inherited a code base where the team is using classes with static methods instead of functions for helper methods. I've never seen this approach taken and trying to decide if I should have them go back and create functions out of them. I feel like this is unclean and bloats imports since you're importing the entire class instead of just the function you're intending?

Is one approach better than the other?

For example's sake in case I'm not being clear:

    export class StringUtil {
      public static alterString(str: string) {
        return alteredString;
      }
    }

vs

    export function alterString(str: string) {
      return alteredString;
    }

This would then be used like so:

import { StringUtil } from '../StringUtil';

getString(str: string) {
  return StringUtil.alterString(str);
}

vs

import { alterString } from '../helper-functions';

getString(str: string) {
  return alterString(str);
}
ye-olde-dev
  • 1,168
  • 2
  • 17
  • 29

2 Answers2

32

Functionally, both implementations will produce the same result with the only difference being that for static methods the function is attached to the class' prototype. If you don't actually need that behavior (unlikely that you do), I'd keep you static methods as separate functions as this is better for tree-shaking and code-splitting (unless you have a LOT of static methods though, these will be only minor gains). In practice, I find that static methods usually only appear for two reasons: (1) whoever wrote the code is used to Java and (2) some IDEs present warnings that you should mark methods as static if they don't use instance variables.

If you just want that ability to namespace a bunch of static methods, you can still do so by exporting an object with all of the individual functions attached.

Jclangst
  • 1,274
  • 7
  • 11
  • 12
    The problem I see with this approach is that auto import features became messy, because you could end up with functions that don't have a meaningful name if not in the context (for example, a `get()` method, if you start with `get` you might end up with a lot of other results, but with `HttpUtil.get()` you can easily autoimport `HttpUtil` and you can autocomplete with `get()` easily, assuming your editor has autoimport features). **The class acts as a namespace in this case**. The downside is that you probably won't benefit from **treeshaking**. – Lucas Basquerotto Sep 11 '20 at 15:27
  • @LucasBasquerotto, if namespacing is an issue, you can just import the module and give it a name: `import * as httpUtil from '...';` You could then call `httpUtil.get()`. At least you get the option to do this where static methods do not. – Jeff Mercado Oct 05 '21 at 06:46
  • @JeffMercado I always use autoimport features for faster development (unless for some unsupported cases, like css modules, for now), so having to rename imports would not be a very good approach IMO, unless absolutely needed. Actually, in most cases, I don't even touch the imports section. – Lucas Basquerotto Oct 05 '21 at 12:35
  • 2
    I upvoted this after reading >>> (1) whoever wrote the code is used to Java – mchouhan_google Jan 24 '22 at 10:33
4

For readability in big files having many imports it’s better to use

return StringUtil.alterString(str);

as it was mentioned in Lucas Basquerotto’s comment

See also discussion at ES6 modules: Export single class of static methods OR multiple individual methods

Michael Freidgeim
  • 26,542
  • 16
  • 152
  • 170