wolfgang ziegler


„make stuff and blog about it“

let auto var - Just Use Type Inference!

February 15, 2024

This blog post has the potential of becoming a bit of a rant and I apologize for that. But seriously though: it's 2024, I still find myself having these (pointless) discussions about type inference, and frankly this is infuriating.

"Please state your types explicitly, it's important for readers of your code".

If I have to read another comment like this one more time, I think I'm gonna scream 😱.

This statement is wrong for so many reasons. But OK, let's indulge and lay them out one last time.

The IDE Use Case

Let me stop you right there. There's really no point at all in discussing this any further.

If you really care about knowing a variable's type and your IDE does not expose this info (as a tooltip or similar) your IDE sucks! Get a better IDE! Case closed.

This is how it should work.

IDE provides the type as tool tip

The PR Use Case

So, the IDE use case is out of the way and hopefully buried forever. But sure as hell, the PR (code review) use case follows right away.

"But what about GitHub, BitBucket, ... I don't have type tooltips there."

No, you (usually) don't. And the whole code-review and PR process is fundamentally broken IMHO. I know. In a perfect world (or rather today) every code review process should offer the same rich features as the local development process. But that's not a type inference problem. It's a a general one. So let's not abuse this fact to drag a single aspect into the mud here.

Apart from that, all you're doing with this argument is arbitrary and weird cherry picking. If you really cared about explicit types so much, you would have to forbid other idioms and programming constructs as well. What do I mean by that? I'll give you some examples:

  • For some inexplicable reason, Lambda expression are usually considered OK. Rather inconsistent, don't you think?

    • someObject.foo(item => ...)
  • You can't have fluent interfaces anymore:

    • someObject.foo().bar().baz("Hello) ... where are you precious type declarations now?
  • Or (nested) Builder patterns:

    • someObject.fooBuilder("bla", 23).barBuilder().build().
  • No direct passing of temporary values:

    • someObject.foo(bar())- that must be forbidden as well following the logic above.
  • Or event regular method calls for that matter:

    • foo(someObject) - Where's the type declaration of foo's argument? Depending on the respective language anything can happen from a simple covariant call to an arbitrarily complex cast Operation that is invoked for someObject.

So, if your code base eliminates all these cases (which I doubt), we can maybe have this discussion. Otherwise, please for the love of God, don't treat type inference like it's somehow special and shut up about it.

Summing it up

Bottom line: your argument is invalid. I rest my case.

Zoidberg meme: Your argument is bad and you should feel bad