Rules / Correctness / unnecessary-nullable-return-type

unnecessary-nullable-return-type

lint/correctness/unnecessary-nullable-return-type
recommended
Same as unnecessary_nullable_return_type · Pyramid Lint

Disallow nullable return types on functions that never return null.

Flags a function or method whose return type is nullable (T?) even though every return in its body yields a provably non-null value. A needless ? forces callers to null-check a result that can never be null, spreading defensive code that adds no safety. Drop the ? from the return type. Only the outer nullability counts, so Future<T?> and List<int?> are left alone. Without full type resolution the check is conservative: it fires only when the body has at least one return and every returned expression is a literal or constructor invocation — any return it cannot prove non-null (a variable, a call, await, or a bare return;) suppresses the report.

Invalid

example.dartdart
// Bad: an outer-nullable return type whose every return is a non-null literal.

String? getStatus() {
  return 'active';
}

int? getNumber() {
  return 42;
}

// The outer `?` (after `List<...>`) counts; the returned list is non-null.
List<String?>? getItems() {
  return ['a', 'b', 'c'];
}

bool? isValid() {
  if (DateTime.now().isUtc) {
    return true;
  }
  return false;
}
Function return type is unnecessarily nullable
2
3String? getStatus() {
Function return type is unnecessarily nullable
6
7int? getNumber() {
Function return type is unnecessarily nullable
11// The outer `?` (after `List<...>`) counts; the returned list is non-null.
12List<String?>? getItems() {
Function return type is unnecessarily nullable
15
16bool? isValid() {

Valid

example.dartdart
// Good: return type is non-nullable when function never returns null

Future<String> getName() async {
  return 'hello';
}

String getStatus() {
  return 'active';
}

int getNumber() {
  return 42;
}

List<String> getItems() {
  return ['a', 'b', 'c'];
}

Future<bool> isValid() async {
  return true;
}

// Good: nullable return type when function can return null

String? maybeGetName(bool shouldReturn) {
  if (shouldReturn) {
    return 'hello';
  }
  return null;
}

int? findIndex(List<int> items, int target) {
  try {
    return items.indexOf(target);
  } catch (e) {
    return null;
  }
}

// Good: only the OUTER `?` counts — a nullable type argument does not.
Future<String?> asyncName() async {
  return 'hello';
}

Future<bool?> asyncValid() async {
  return true;
}

// Good: returns we cannot prove non-null are not flagged.
String? fromVariable(String value) {
  return value;
}

String? fromCall() {
  return compute();
}

String? withNullBranch(bool flag) {
  if (flag) {
    return 'x';
  }
  return null;
}

How to configure

Set the severity of unnecessary-nullable-return-type in your falcon.json:

falcon.jsonjson
{
  "linter": {
    "rules": {
      "correctness": {
        "unnecessary-nullable-return-type": "error"
      }
    }
  }
}