Type System in Dart
Dart language is a type safety enabled language that uses static and dynamic type checking to match the value of the variable with its data type at the compile-time. This is also known as sound typing. Although the types are mandatory, data type annotations are optional because of the type interference.
The static type checking is really advantageous as it has the ability to find the errors at the compile time using the static analyser of Dart. Most of the bugs interpreted by the static analyser can be fixed by declaring the generic classes along with the type annotations.
The most common generic classes are the collection types which are as follows :
- List< T >
- Map< K, V >.
For example, in the following code the int_list( ) function prints an integer list, and main( ) functions creates a list and passes it to the int_list( ) function.
Consider the following code in Dart that uses collection types :
Example – 1 :
void int_list( List< int > a) => print( a ) ;
void main( )
{
var list = [ ] ;
list.add( 5 ) ;
list.add( ' Yukta ' ) ;
int_list( list ) ;
}
Output :
The code did not compile as it resulted in a type error on the list when the function int_list( ) function is called.
Error :
Error compiling to JavaScript:
Info: Compiling with sound null safety
Warning: Interpreting this as package URI, 'package:dartpad_sample/main.dart'.
lib/main.dart:7:13:
Error: The argument type 'List<dynamic>' can't be assigned to the parameter type 'List<int>'.
- 'List' is from 'dart:core'.
int_list( list ) ;
^
Error: Compilation failed.
The error highlights an unsound implicit cast from List< dynamic > to List< int >. The list variable has static type List< dynamic >. The definition of the list as
var list = [ ]
does not provide clear information to the type analyzer to interpret the type argument more specific than dynamic. The int_list( ) function expects a parameter of type List< int >, causing a mismatch of types.
Let us try to debug the above code.
We must begin with specifying a type annotation ( < int > ) while defining that list. It should be like :
var list = < int >[ ] ;
But still, the problem isn't solved completely. The analyzer throws an error that the string type value can not be assigned to the integer type parameters as in the line :
list.add( ' Yukta ' ) ;
To solve this problem as well, we must add only the integer value like :
list.add( 2 ) ;
This will result in code passing static analysis and running with no errors or warnings.
void int_list( List< int > num ) => print( num ) ;
void main( )
{
var list = < int >[ ] ;
// adding the integer elements to the list
list.add( 5 ) ;
list.add( 10 ) ;
list.add( 15 ) ;
// printing the list
int_list( list ) ;
}
Output :
[5, 10, 15]
What is soundness?
Soundness helps to ensure that the program successfully gets over the invalid states. A sound type system used in the program enables that the program never gets into a state where an expression is evaluated to a value that doesn't match the static type of the expression. For example, if an expression has a type ' String ' at the time of compilation, you are guaranteed only to get a string when you evaluate it at the run time.
Like in any other programming language such as Java and C#, the type system of Dart is sound. It enforces soundness using a combination of static checking ( compile - time errors ) and dynamic checking ( at runtime ). For example, assigning a String to int is a compile - time error. Casting an object to a String using as String fails with a runtime error if the object isn't a String.
The benefits of soundness
Sound type system has many benefits. Some of them are as follows :
- Revealing type-related bugs at compile time : A sound type system ensures that the code is unambiguous with respect to the data types, such that the type - related bugs that might be difficult to find at runtime are successfully revealed at compile time.
- More readable code: Code becomes more readable with the sound type safety because one can rely on a value actually having the exact specified data type. In sound Dart, types can’t lie.
- More maintainable code : With a sound type system, whenever a piece of code is changed let us say the data type of a variable, the type system highlights and warns the programmer about the other places where the data type is still the old one.
- Better ahead of time (AOT) compilation: While AOT compilation is possible without types; the generated code is much less efficient.
Tips for passing static analysis
Most of the rules for static types are easy to understand. Here are some of the less obvious rules:
- Use sound return types when overriding methods.
- Use sound parameter types when overriding methods.
- Don’t use a dynamic list as a typed list.