Introduction
Typically, computer languages have fallen into two camps:
- Statically-typed languages.
- Dynamically-typed languages.
Statically-typed Languages
These languages have specific variable types and the developer compiles the code using an ‘ahead-of-time’ compiler. The compiler type checking is performed before the code is run. This is an excellent way to develop software as the compiler performs static-analysis of the code as part of the compilation, alerting the developer when issues arise. Software typically takes longer to develop in this method, but the software developed in this manner typically works better in complex scenarios.
Dynamically-typed Languages
These languages don’t have specific variable types and no ahead-of-time compilation is performed. Dynamically-typed languages make the development process very quick as the developer does not typically need to recompile the code. However, code developed in this manner tends to lend itself to simpler scenarios as it can be more error-prone. Less analysis and checking = more potential errors.
Dart & Typing
Dart is different because Dart code can be run with both static types and dynamic type variables. The type system in Dart 1 had some issues and they introduced a ‘strong mode’ for stronger type checking. This mode has become the typing system in Dart 2.0 and it offers strong guarantees that an expression of one type cannot produce a value of another type.
Dart performs type checking at two different times:
- When the code is compiled (code is reloaded / or compiled ahead-of-time).
- When the code is run (runtime).
Static Types
Type |
Description |
int |
Integers (no decimals). |
double |
Decimal number (double precision). |
bool |
Boolean true or false. |
String |
Immutable string. |
StringBuffer |
Mutable string. |
RegExp |
Regular expressions. |
List, Map, Set |
Dart provides Collection classes. |
DateTime |
A point in time. |
Duration |
A span of time. |
Uri |
Uniform Resource Identifier |
Error |
Error information |
Dynamic Types
You can define untyped variables by declaring them using the ‘var’ or ‘dynamic’ keywords.
- The ‘var’ keyword declares a variable without specifying its type, leaving the variable as a dynamic.
- The ‘dynamic’ keyword declares a variable of the type ‘dynamic’ with optional typing.
There is a difference but it is subtle: see this blog post for more information:
Dynamic Types & Type Inference
When the code uses dynamic types, their 'type' is calculated at runtime using inference. At runtime (when the program runs), the runtime figures out what the variable types are based on the values they are set to. This usually works well – see (‘Example of Inference #1’) but can cause problems if a variable type is inferred at one point in the code then another type is inferred later on – see ‘Example of Inference #2’ below.
Example of Inference #1:
void main() {
dynamic x = 1;
if (x is int){
print('integer');
}
}
Output:
'integer'
Example of Inference #2:
void main() {
dynamic x = 'test';
if (x is String){
print('String');
}
x += 1;
}
Output:
String
Uncaught exception: TypeError: 1: type 'JSInt' is not a subtype of type 'String'
This is because the code is attempting to increment a variable (as if it was a number) that has an inferred type of 'String'.
Part 2 coming soon!