The curious case of void in Dart

I think thevoid type is the most curious and subtle type in Dart. As of now, I have got enough experience with Dart that I’m able to explore almost every topic in Dart. But guess what, it surprises me like always. Whenever I began to think that now I have explored all the major parts of the language, it hits me in the head with a brick. At first, it seemed frustrating and difficult to grasp, I tried searching about void on the official docs and all other places on the internet that could solve my problem but what I found was just this article which opens when you click on the void keyword on the official docs. Since most of my programming days are passed with Java and Android, and Dart is almost similar to Java in comparison to syntax but in some places, it just takes another path far from the way Java does it.

😯 What Confuses about void in Dart?

If you are coming from Java or some other similar programming language then probably you are comfortable with the thing that method or function with return type void doesn’t returns anything. But in Dart that doesn’t works and void is not that simple to grasp.

Initially lets see how void return type behaves in java:

Here, MyVoid is a simple class which contains a method show with return type void . Since the return type is void the method prints Good Morning World!! and exits without returning anything. I think things are pretty clear right away but now we will look at how Dart handles void types.

Note: Every function in Dart returns a value, if you are not declaring it explicitly then null will be returned by default.

In the above program either we can return something or we can leave it, if we do not return anything then by default null is returned.

What we are doing here is declaring a top level method show with return type void which is called in the main method, one thing that you should focus on is show method is returning print method which would be invalid in languages like Java. Since in Dart almost everything is an object including functions/methods which are object of class Function and we are allowed to do some more stuff with Function like :

  • Declare it as a parameter
  • Pass it as an argument
  • Assign it to a variable
  • Return a function from a function
  • Return a result of a function from a function (This is what we are doing above)

So, now you must understand that Dart functions are no ordinary methods, in fact they are functions on steroid. Now returning to our code above, inside show method we are first executing the method print and after that, we are returning the result of print method.

Note: The return type only specifies what the DartAnalyzer warns you about. There are type checks now in Dart2 that also check that at runtime.

If the return type of show function is void then only three things can be returned, returning any other result will cause a type warning.

1 ) Return null

2 ) Return dynamic variable

3 ) Return void function

But even if Dart allows to return these three things in a void function, it doesn’t allow us to use these returned values from a void function.

For example the code below will not compile:

Because Dart doesn’t allow us to use the values returned by void functions. Once we change the return type of the show method, we can use the value returned by the method.

Here, the value = null , do you know why?

Inside show method we are executing print method, which will print Good Morning World. If no value is explicitly returned, then null is returned. null is (or would also be) returned when the return type of show is void, but Dart refuses to compile so it doesn’t come to that.

😑 Things are more chaotic when we use Shorthand Function () =>

Can you guess Is the above program valid or not?

The program will compile without any error and it is 100% valid. If you guessed it then congrats and if not then don’t think too much about it, as it happened with me also. Yes you can ask that the return types are void then how can we return int , String , bool or a function ? So the answer is you can return anything from a shorthand function with return type void but guess what? You can’t communicate with or use those returned values in any way.

So why is returning everything allowed through a shorthand function[()=>] even if the return type is void?

As we have discussed above in normal functions with return type void we can only return three types of values(i.e void , null and dynamic) but in shorthand function things are little different because shorthand functions always returns a value and if we limit the values that could be returned then functions with void return types will become invalid. Lets take an example of setter function as the default return type of every setter is void and they are often declared as a shorthand function.

If you have learned Dart then probably you know that every instance variable in Dart has a getter and setter implicitly. Indeed Dart gives some extra privilege to getter and setter methods treating them like special methods.Look at the code below, here we are setting value to library private instance variable _val using a setter —

Setter are declared using the keyword set in Dart and their return type must be void or absent. If it is absent it is void implicitly. And remember every shorthand function implicitly declares the return keyword, which means you don’t have to declare return keyword instead it is automatically added in the shorthand function. The expression _val = val is an assignment expression and it returns the value assigned. If shorthand functions are not designed in such a way that it allows all types of values to be returned by void then the setter methods will become invalid. You can think of it as a kind of settlement and their’s fair number of discussion going on the topic inside Dart community. Also Dart is an evolving language so you can expect things can change in near future.(and may be not in this case)

☀️ One more thing!

Until Dart 1 void is only usable as a return types of functions (like void main() ) but from Dart 2(along with static checking, runtime type safety, optional new/const, core library improvements, and more), void has also been generalized. So what does that mean? 🤔

Dart gives a very gentle way to handle asynchronous code that looks very similar to the synchronous code. I personally like this feature very much. When we are working with Futures , there are many situations when we don’t want to get a result when our asynchronous work is done. Before Dart 2 we have to useFuture<Null> for this but ever since the release of Dart 2, things are better , as now we can do it like this Future<void> .

Here I don’t want anything to be returned after the cache is cleared so we are using void as a type parameter. Also we can almost achieve the same thing with Future<Null> . void was not allowed in Dart 1 as generic type parameter and that’s why Future<Null> was used for that purpose.There could be whole lot of other things which we can discuss about them but for now just keep in mind that void will allow to return any value but you can’t use or communicate with the values returned(if you try to do so, you will get a warning) and Null only allows to return null .

Thanks for reading. If you liked this one, you should follow me for the next one. 🙏

Thank You Günter Zöchbauer for the Proofreading and for all the awesome work you are doing on Stackoverflow for the Dart Community.

If you have any questions, feel free to post them 👇.

Any feedback is welcome 😃.

If you enjoyed this story, you can support me by 👏 this.
You can also follow me on Twitter , Facebook or Instagram.