100 lines
2.4 KiB
Plaintext
100 lines
2.4 KiB
Plaintext
Don't null check (i.e. `!`) a potentially nullable type parameter.
|
|
|
|
== Why is this an issue?
|
|
|
|
Given a type parameter `T`, the type `T?` is nullable version of `T`, i.e. A variable `x` of type `T?` can either hold a value of type `T` or `null`.
|
|
|
|
However, when `T` itself is bound to a nullable type, a variable `y` of type `T` can hold a `null` value by itself. For example, if `y` is defined as `int?`, `null` is a valid value for `y`.
|
|
|
|
Therefore, when `T` is bound to a nullable type, `x` can hold `null` as a valid value, which means that `x!` is an incorrect check for the validity of `x`, since it would raise a runtime exception when `x` holds `null`.
|
|
|
|
[source,dart]
|
|
----
|
|
void main() {
|
|
int? x = null;
|
|
bangT(x); // Throws a runtime exception
|
|
asT(x); // Returns null
|
|
}
|
|
|
|
T bangT<T>(T x) => x!;
|
|
T asT<T>(T x) => x as T;
|
|
----
|
|
|
|
== How to fix it
|
|
|
|
Use the `as` operator, instead of the `!` operator. `as T` will not raise exception when `x` is `null` and `T` is bound to a nullable type.
|
|
|
|
=== Code examples
|
|
|
|
==== Noncompliant code example
|
|
|
|
[source,dart,diff-id=1,diff-type=noncompliant]
|
|
----
|
|
void main() {
|
|
getOrDefaultIf<int?>(() => 42, false);
|
|
}
|
|
|
|
T getOrDefaultIf<T>(T retriever(), bool condition) {
|
|
T? result;
|
|
final retrieveIfCondition = () {
|
|
if (condition) {
|
|
result = retriever();
|
|
}
|
|
};
|
|
|
|
retrieveIfCondition();
|
|
return result!; // Noncompliant
|
|
}
|
|
----
|
|
|
|
==== Compliant solution
|
|
|
|
[source,dart,diff-id=1,diff-type=compliant]
|
|
----
|
|
void main() {
|
|
getOrDefaultIf<int?>(() => 42, false);
|
|
}
|
|
|
|
T getOrDefaultIf<T>(T retriever(), bool condition) {
|
|
T? result;
|
|
final retrieveIfCondition = () {
|
|
if (condition) {
|
|
result = retriever();
|
|
}
|
|
};
|
|
|
|
retrieveIfCondition();
|
|
return result as T;
|
|
}
|
|
----
|
|
|
|
== Resources
|
|
|
|
=== Documentation
|
|
|
|
* Dart Docs - https://dart.dev/tools/linter-rules/null_check_on_nullable_type_parameter[Dart Linter rule - null_check_on_nullable_type_parameter]
|
|
* Dart Docs - https://dart.dev/null-safety[Language - Null safety]
|
|
* Dart Docs - https://dart.dev/null-safety/understanding-null-safety#non-null-assertion-operator[Language - Non-null assertion operator]
|
|
|
|
|
|
ifdef::env-github,rspecator-view[]
|
|
|
|
'''
|
|
== Implementation Specification
|
|
(visible only on this page)
|
|
|
|
=== Message
|
|
|
|
* The null check operator shouldn't be used on a variable whose type is a potentially nullable type parameter.
|
|
|
|
=== Highlighting
|
|
|
|
The `!` operator in `<variable>!`.
|
|
|
|
'''
|
|
== Comments And Links
|
|
(visible only on this page)
|
|
|
|
endif::env-github,rspecator-view[]
|
|
|