Myths about F#: Code without type annotations is hard to review! No, it’s a relief.

After one of my presentations about F#, we had a discussion about the effect of type inference, resulting in almost no type annotations, on code readability and reviewability. The concern was that it makes the code harder to understand, especially when reviewing code, for example, outside of an IDE (GitHub/Azure DevOps/… Pull Requests).

So is there a problem or not? Let’s see.

The effect of the absence of type annotations on readability

I can only talk from our experience. Maybe you can add yours in a comment?

When reading code while adding some feature, we normally are interested in understanding the flow of the code and how we can fit the new feature into the existing code. We do this in an IDE. In this scenario, I prefer not to have type annotations everywhere. They are simply not necessary. And in the rare case that I want to know the type, the IDE can tell me by hovering the mouse over a value. Not having type annotations everywhere makes reading code easier and faster.

Reviewing Code

When reviewing code, it heavily depends on where you review code. We use Azure DevOps, and we use the Pull Request feature to work on a single feature and to release it as a whole (when the branch is merged to main). We can have a discussion about trunk-based-development and why we don’t follow it for most coding at another time.
Reviewing inside Azure DevOps (or GitHub) has some disadvantages: the syntax highlighting is not as good as in the IDE, I can’t hover over a value to see its type, I can’t navigate in the code by using Go-To-Definition as I can in an IDE. The advantages of reviewing inside of these online git tools are that I can create comments, mark files I have already reviewed and provide a place for a written discussion about the whole thing that is reviewed.

As you see, not knowing the types of values is only one of several problems when reviewing inside Azure DevOps, GitHub, GitLab or any other online git tool.

Stay in the IDE

That’s why we review code for more complicated cases inside of our IDE (Rider in our case). We pull the branch to be merged locally and let the IDE-integrated git tool show us the differences to the main branch. Et voilà, we can hover over values to get their type, we can navigate in our code, we have nice syntax highlighting, and all the other benefits of a fully-fledged IDE.

The drawback is that we can’t comment directly in the code. We are currently experimenting with the following solution. We create a channel in our chat tool for the review and add a message per review finding. When we start a discussion on a single review finding, we add a thread to the message. Not as elegant as in the online review tool because we need to annotate the filename and line number by hand. My hope is that Rider will eventually support reviewing PRs directly and with comments.

This works for us; we typically have only a few review findings because we try to keep the reviews short, we have typically talked about the code in pairs or even the team a couple of times before the review, and we use tools for simple things like syntax (Fantomas).


For most code being read or reviewed, type annotations are not necessary – they often simply add noise. In cases when knowing a type is helpful during a review, I often miss navigation capabilities even more. Therefore, I switch from the review tool to my IDE with all its features supporting reading and navigating code. The only drawback is that writing down a review finding is a bit more work.

Overall, not having to annotate types everywhere outweigh the disadvantages when reviewing by far: less noise, thus easier to read code, easier to write code, and easier to refactor code.

About the author

Urs Enzler


By Urs Enzler

Recent Posts