const, final, dynamic, var... when and why?
Tags: dart, flutter, tutorial, beginners
Published: 2022-07-29 15:18:22

One of the first things explained in most tutorials and programming guides is the use and declaration of variables. In Dart, you could declare those with `const`, `final`, `dynamic`, `var`, and by using the type itself; but what are their differences and when should we use each one?

> 📽 Video version available on [YouTube](https://youtu.be/DFe0Aag7V5k) and [Odysee](https://odysee.com/@svprdga:d/const-final-dynamic-var-when-and-why-dart-flutter-tutorial:7)

{% embed https://youtu.be/DFe0Aag7V5k %}

Choosing the correct declaration is crucial to writing clean, safe, and performant code. Let's see each one in detail and when we should use it:

## var

`var` is short for variable. It is used to declare a variable whose type is statically inferred:

```dart
var text = "hello";
```

In the example above we are declaring a variable of type `String`. Dart is able to infer the type, which means that there are times when it is able to know what type it is by the value that we have given. In this case, when assigning a text string delimited by the `"` characters, it is quite evident that it is a `String`.

Just because we defined that variable using `var` doesn't mean we can change its type later:

```dart
var text = "hello";
text = 10;
```

If we execute that piece of code, the compiler will fail and will let us know that we cannot change the type of a variable.

Another way to declare variable properties is directly using the type identifier instead of the `var` keyword:

```dart
var first = "first";
String second = "second";
```

In this example we are creating a variable of type `String` with value _first_, and then a variable of type `String` with value _second_.

It is considered good practice to be explicit about the type declaration when declaring a property of a class, whereas variables in a smaller scope such as a method we can use the `var` keyword:

```dart
class MyClass {
   String name = "David";
  
   void someMethod() {
     var anotherName = "Tom";
   }
}
```

Using any of the previous methodologies we can create variables whose value is reassignable:

```dart
var text = "hello";
print(text); // Prints: hello
text = "bye";
print(text); // Prints: bye
```

In short, we should use `var` (or the name of the type) when we want to declare a variable when we know its type and that it is going to be modifiable during the execution of our program.

## dynamic

`dynamic` is similar to `var` in that it is a variable whose value can be changed during program execution, but its type can also vary:

```dart
var text = "hello";
text = 10; // Throws an error

dynamic otherText = "otherText";
otherText = 10; // This is fine
```

Generally speaking, you should avoid using `dynamic` for your variable declarations as much as possible. The reason is not knowing the type can lead to unexpected errors, something you've probably experienced if you've ever worked with a dynamically typed language like _javascript_.

That's not to say that it can't be useful on some occasions though, a typical example would be decoding a JSON value:

```dart
final json = jsonDecode(content) as Map<String, dynamic>;
```

In this example we are decoding a JSON value as a map of `String` and `dynamic`. We know that each identifier is going to be a `String`, but we don't know what type each value will have, so we use `dynamic`. Finally, to use any of the values, we should perform a type check to avoid errors:

```dart
final json = jsonDecode(content) as Map<String, dynamic>;

if (json['text'] is String) {
   String text = json['text'] as String;
}
```

In short, `dynamic` should be used only for variables whose type is unknown.

## final

`final` is a keyword that we use to declare variables whose value can't be reassigned, which means that its value won't change. Its use is recommended whenever possible:

```dart
final String text = "this value will never change";
```

It can also be shortened using type inference:

```dart
final text = "this value will never change";
```

It's important to note that `final` cannot be used together with `var`:

```dart
final var text = "final var"; // Throws an error
```

As I said, the `final` variables cannot be modified:

```dart
final text = "final var";
text = "another text"; // Throws an error
```

The recommendation is to use `final` whenever we know that a value cannot change, but to apply this rule we must first know `const`:

## const

`const`, like `final`; is an immutable variable whose value cannot be changed; but it has to be a compile-time constant:

```dart
const text = "const value";
```

If this constant value is in the body of a class, it's best to mark it as `static` for further optimization:

```dart
class MyClass {
  static const text = "const value";
}
```

Since the value must be evaluable at compile time, it is not always possible to use it. The general rule for variables whose value is not going to change is to use `const` whenever possible and `final` otherwise.

```dart
class MyClass {
  static const text = "const value";
}

void main() {
  const instance = MyClass(); // Throws an error
}
```

This code will fail since _MyClass_ is not a constant value, however if we replace `const` with `final` we will get a working and efficient code:

```dart
class MyClass {
  static const text = "const value";
}

void main() {
  final instance = MyClass();
}
```

Another possible solution is to declare _MyClass_ as a constant value by using `const` in its constructor:

```dart
class MyClass {
  static const text = "const value";
  
  const MyClass();
}

void main() {
  const instance = MyClass();
}
```

## const in the context of Flutter

It is recommended to use `const` constructors whenever possible when creating Flutter widgets. The reason is the performance increase, since Flutter can save some calculations by understanding that it can reuse that widget from a previous redraw in the current one, since it is a constant value.

[Here](https://medium.com/nerd-for-tech/flutter-performance-analysis-of-const-constructor-d2a72fd8a043) is a very interesting article by [Crizant Lai](https://medium.com/@crizantlai) that analyzes the performance impact of using a widget with or without a `const` constructor.

## Conclusion

In this article we have seen the differences between `const`, `final`, `dynamic` and `var` and when to use each one. If you want to learn more details about Dart and its type system I invite you to go to the [Dart language tour](https://dart.dev/guides/language/language-tour).

Thank you for reading this far,

Happy coding!