Flutter Community
Published in

Flutter Community

Dart type you have NEVER used

Dart type system goes: never say never…

First of all, the title of this article could seem like just another clickbait but let me explain. Sure, there is a chance that you have used this type, but for the sake of a pun (and I REALLY enjoy them), I had to do it - oh well, here we are now. The thing is, the type I am going to talk about in this article is actually called Never.

Note: all the information provided in this article is based on the official Dart language documentation.

Table of Contents

  • Dart type system before and after null safety
  • When should I use “Never” in my code?
  • Your contribution

Dart type system before and after null safety

Dart type system before (left) and after (right) null safety

To understand the concept of the type Never, first, we must understand the difference between the Dart type system before and after null safety. That was never an easy task for me, but let’s try.

Before sound null-safety in Dart, Null was a subtype of all types (look at the graph on the left in the picture above). After introducing null-safety, the Null type is no longer a subtype of all types (the right graph in the same picture above), all types became non-nullable by default — and you could hear this everywhere when talking about sound null-safety of Dart.

However, by looking at this new Dart types’ structure, we cannot easily identify what’s the top-most and bottom-most type. Well, for the top-most type it is quite clear: we do not have a dedicated named type, but we can define it as a nullable Object (Object?) — a combination of Object and Null types. When you think about it, every nullable type is just a combination of any non-nullable type and Null. For instance, double + Null = double?, String + Null = String? and so on.

Ok, but how about the bottom-most type? For this, the Dart team went brrrr and just simply introduced a new named type called Never.

This new bottom type has no values. However, you can use it as a type annotation. How, why? Let’s check it out👇🏻

When should I use “Never” in my code?

I do adore how this type is described in the documentation:

On the rare occasion that you need a bottom type, use Never instead of Null. If you don’t know if you need a bottom type, you probably don’t.

Ok, but there are cases when the type Never could be used in the code. Whether that’s useful or not, I will leave it for you to decide.

When the return type of an expression is Never, what does it mean? Well, you could say that it should return something of type Never, but it indicates that the expression can never successfully finish evaluating. Does it mean that the expression or function would get stuck at that point? No, just “it must throw an exception, abort, or otherwise ensure that the surrounding code expecting the result of the expression never runs.” This idea could be applied when creating helper functions for validation:

// User data class
class User {
final String email;
final String password;
const User({
required this.email,
required this.password,
});
@override
String toString() => 'User {email: $email, password: $password}';
}
// Helper function for required field validation
Never isRequired(String property) {
throw ArgumentError('$property is required.');
}
void main() {
String? email;
String? password;
// ...
// Some code to get email and password
// ...
if (email == null || email.isEmpty) isRequired('email');
if (password == null || password.isEmpty) isRequired('password');
final user = User(email: email, password: password); // ...
// Do something with the user data
// ...
}

This example compiles without any error!

Notice that email and password are required properties when creating the User object and there is no return or throw keywords in the validation code. The control flow analysis knows that the return type of isRequired() helper function is Never, hence in case of any if condition being true, the code must abort somehow. It allows using email and password as non-nullable variables later on.

In other words, using Never in your own APIs lets you extend Dart’s reachability analysis.

In my opinion, there is not much difference between throwing a custom exception and using a helper function of type Never. However, if you find such implementation convenient, feel free to use it in your code!

Thank you for reading, and let me know whether you have ever used the type Never in any Dart or Flutter project!

Your contribution

👏 Press the clap button below to show your support and motivate me to write better!
💬 Leave a response to this article by providing your insights, comments or requests for future articles.
📢 Share this article with your friends, colleagues on social media.
➕ Follow me on Medium and check other articles.
🍿 Subscribe to my YouTube channel — more content is coming soon!
✉️ Do not hesitate to DM me on Twitter and share your opinion about… anything!

Follow Flutter Community on Twitter: https://twitter.com/FlutterComm

--

--

--

Articles and Stories from the Flutter Community

Recommended from Medium

How to Add Color to SVG Icons and Elements With CurrentColor

Using MapStruct with Maven and Lombok

Programming’s Impact On Brain

Distributed Transactions & Two-Phase Commit

Building a chat system with Flutter and Cloud Firestore

History of SQL

How to wrap your imperative brain around functional reactive programming in RxJava

Java Optionals

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Mangirdas Kazlauskas

Mangirdas Kazlauskas

Google Developer Expert for Flutter & Dart | Software Engineer - https://twitter.com/mkobuolys

More from Medium

How to make your Flutter app offline-first with Couchbase Lite

Flutter Performance Tips — Part 2

Top 8 State Managements for Flutter 2022

Flutter State Management: 2022 Edition