This document specifies the "Strict casts" mode enabled with a static analysis option, new in Dart 2.16. As a static analysis option, we only intend to implement this feature in the Dart Analyzer. Under this feature, any implicit cast is reported as an analyzer "Hint" (a warning).
Note that under the null safe type system, the only expressions which may be
implicitly cast are those with a static type of dynamic
. These are exactly
the implicit casts reported in the strict casts mode.
To enable strict casts, set the strict-casts
option to true
, under
the Analyzer's language
section:
analyzer:
language:
strict-casts: true
Static analysis can provide many benefits which require meaningful static
types. For example, when a value of one type is not assignable to a variable
of another type, the error is reported by static analysis. However, when a
value has a static type of dynamic
, no error is reported. Such a value is
always assignable, because a cast is implicitly inserted at runtime, which may
fail. For example:
import 'dart:convert';
void main() {
var decoded = jsonDecode(/* some JSON */);
if (decoded['foo']) {
print('Got foo.');
}
}
The expression used in an if-statement's condition must have a static type of
bool
. Without the strict casts mode, an expression with a static type of
dynamic
(such as the example's decoded['foo']
) is allowed, due to the
implicit cast to bool
which will occur at runtime. The strict casts mode aims
to warn about such code during static analysis.
Note that another way to root out implicit casts from the dynamic
type is to
ban all use of the dynamic
type. However, there are many common APIs which
return dynamic
-typed values, such as the dart:convert
library's
JSON-decoding functions (referenced in the example above). The strict casts
mode allows the use of such APIs, requiring only that such dynamic
-typed
values are explicitly cast before using them in a position where a value of
non-dynamic
type is expected.
The strict casts mode is very similar to another static analysis mode supported by the Dart analyzer: "no implicit casts," now deprecated in favor of the strict casts mode. The new mode reports all of the same implicit casts which the "no implicit casts" mode does, and it also reports three more cases, detailed below.
A value with a static type of dynamic
which is used as the iterator
expression in a for-in loop is reported. For example:
void foo(dynamic arg) {
for (var value in arg) { /* ... */ }
}
A value with a static type of dynamic
which is used as the expression in a
spread is reported. For example:
void foo(dynamic arg) {
[...arg];
}
A value with a static type of dynamic
which is used as the expression in a
yield-each expression is reported. For example:
Stream<int> foo(dynamic arg) async* {
yield* arg;
}