How can I make sure that a non-nullable type will always be inferred?

Viewed 254

I'm currently making an API that I want the optional value of type T to never be nullable (having null-safety enabled, of course).

Let's exemplify with the following:

void main() {
  T nonNullableGeneric<T>(T value) {
    if(value == null) {
      throw 'This is null';
    }

    return value;
  }

  nonNullableGeneric(1); // Works fine
  
  nonNullableGeneric(null); // Works fine BUT I would like that the type inference would not allow a nullable value

  // Now this works as expected:
  // "the argument type 'Null' can't be assigned to the parameter type 'int'."
  // 
  // ... but I have to specify the type `T`, which is not clear given my function signature, that clearly
  // requires a non-nullable value of type `T`
  nonNullableGeneric<int>(null);
  
  // How can I make the following call:
  // nonNullableGeneric(null)
  // to throw me something like "the argument type 'Null' can't be assigned to a parameter type 'T'."?
}

I've also created a dartpad.

As you can see, I must always specify the type if I want to make sure that it can't be Null when using a generic argument.

How can I make sure that it will never allow a nullable type?

1 Answers

I've found that the answer was really obvious, although I think it's reasonable to mention anyways: just make your type T constraints (extend) to a type of Object. This will make sure that that particular argument can never be optional.

Quoting the Object docs:

/// ...
/// Because `Object` is a root of the non-nullable Dart class hierarchy,
/// every other non-`Null` Dart class is a subclass of `Object`.
/// ...

So, in this example that I've mentioned, the solution would be:

void main() {
  T nonNullableGeneric<T extends Object>(T value) {
    return value;
  }

  nonNullableGeneric(1); // Works fine
   
  // Throws a:
  // Couldn't infer type parameter 'T'. Tried to infer 'Null' for 'T' which doesn't work: Type parameter 'T' declared to extend 'Object'.
  // The type 'Null' was inferred from: Parameter 'value' declared as 'T' but argument is 'Null'.
  // Consider passing explicit type argument(s) to the generic
  nonNullableGeneric(null);
}
Related