Skip to content

[Null Safety] Object extension methods on null #1497

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
scopendo opened this issue Mar 5, 2021 · 2 comments
Closed

[Null Safety] Object extension methods on null #1497

scopendo opened this issue Mar 5, 2021 · 2 comments
Labels
request Requests to resolve a particular developer problem

Comments

@scopendo
Copy link

scopendo commented Mar 5, 2021

Prior to null safety, I used a series of extension methods on Object in order to simplify code, especially to avoid ternary operations to pass values to widget parameters, or when a bool expression might return null.

extension ObjectExtension on Object {
  /// Returns true if the current value is null.
  ///
  /// This works because Dart allows Object methods to be called on null.
  bool get isNull => this == null;

  /// Returns true if the current object is not null.
  bool get isNotNull => this != null;

  /// Returns the value of the first positional argument if the current
  /// value is null, otherwise it returns the value of the [otherwise]
  /// named parameter, or null if [otherwise] is not specified.
  T? ifNull<T>(T nullResult, {T? otherwise}) {
    return this == null ? nullResult : otherwise;
  }

  /// Returns the value of the first positional argument if the current
  /// value is not null, otherwise it returns the value of the [otherwise]
  /// named parameter, or null if [otherwise] is not specified.
  T? ifNotNull<T>(T notNullResult, {T? otherwise}) {
    return this == null ? otherwise : notNullResult;
  }

  /// True if the current object is a boolean with the value of true.
  ///
  /// This extension method is helpful for evaluating bool values
  /// that might be null.
  bool get isTrue {
    return (this is bool) && this == true;
  }

  /// False if the current object is not a boolean or does not have
  /// the value of true. See [isTrue].
  bool get isFalse {
    return !isTrue;
  }

  /// Returns the value of the first positional argument if the current
  /// value is true, otherwise it returns the value of the [otherwise]
  /// named parameter, or null if [otherwise] is not specified.
  T? ifTrue<T>(T trueResult, {T? otherwise}) {
    return isTrue ? trueResult : otherwise;
  }
}

It appears that with null safety, these object methods get the error:

The method 'xxx' can't be unconditionally invoked because the receiver can be 'null'.

Examples include:

final String? someOptionalText;

AppBar(
  bottom: someOptionalText.ifNotNull(
      PreferredSize(
        preferredSize: Size.fromHeight(120),
        child: Text(someOptionalText),
      ),
    ),
);

if (someOptionalText.isNotNull && someOptionalText.isNotEmpty) {
  // Prefer the readability of isNotNull over != null, especially with more complex checks
}

Is it intended that object extension methods should no longer be applicable to null?

@scopendo scopendo added the request Requests to resolve a particular developer problem label Mar 5, 2021
@leafpetersen
Copy link
Member

Yes this is working as intended. If you wish your extensions to be applicable to nullable object types, change the on type to Object?. That is:

extension ObjectExtension on Object? {}

@scopendo
Copy link
Author

scopendo commented Mar 6, 2021

Thank you @leafpetersen, that's the missing link that makes sense in hindsight. Object and Object? are different types 👍👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
request Requests to resolve a particular developer problem
Projects
None yet
Development

No branches or pull requests

2 participants