zeba_academy_nullable 0.0.1 copy "zeba_academy_nullable: ^0.0.1" to clipboard
zeba_academy_nullable: ^0.0.1 copied to clipboard

Generic nullable-value utilities for Dart and Flutter, including fallbacks, conditional mapping, null-safe execution, and transformations.

zeba_academy_nullable #

pub package likes popularity license

A lightweight, dependency-free collection of generic nullable-value utilities for Dart and Flutter.

zeba_academy_nullable provides convenient helpers for fallback values, nullable transformations, conditional execution, filtering, first-non-null selection, and other null-safe operations while working naturally with Dart's built-in null-safety system.


Features #

  • ✅ Generic nullable-value utilities
  • ✅ Fallback values
  • ✅ Lazy fallback evaluation
  • ✅ Nullable transformations
  • ✅ Transformations with fallback values
  • ✅ Conditional execution
  • ✅ Null-only execution
  • ✅ Conditional value selection
  • ✅ Nullable filtering
  • ✅ First non-null value selection
  • ✅ Generic fold operations
  • ✅ Convenient extension methods
  • ✅ Fully null-safe
  • ✅ No runtime dependencies
  • ✅ Lightweight and easy to integrate
  • ✅ Works with Dart and Flutter
  • ✅ Suitable for production applications

Installation #

Add zeba_academy_nullable to your pubspec.yaml:

dependencies:
  zeba_academy_nullable: ^0.0.1

Then run:

flutter pub get

For Dart-only projects:

dart pub get

Import #

import 'package:zeba_academy_nullable/zeba_academy_nullable.dart';

Quick Start #

Fallback values #

Use valueOr when you want a fallback value when the original value is null.

String? username;

final displayName = username.valueOr('Guest');

print(displayName);

Output:

Guest

When the value is not null, the original value is returned:

String? username = 'Sarvesh';

final displayName = username.valueOr('Guest');

print(displayName);

Output:

Sarvesh

Lazy fallback values #

Use valueOrElse when calculating the fallback may be expensive.

String? token;

final value = token.valueOrElse(
  () => generateDefaultToken(),
);

The fallback callback is only executed when the value is null.


Nullable transformations #

Use mapNullable to transform a nullable value without manually checking for null.

String? name = 'Sarvesh';

final length = name.mapNullable(
  (value) => value.length,
);

print(length);

Output:

7

When the value is null:

String? name;

final length = name.mapNullable(
  (value) => value.length,
);

print(length);

Output:

null

Transform with a fallback #

Use mapOr when you want a fallback result.

String? ageText;

final age = ageText.mapOr(
  (value) => int.parse(value),
  0,
);

print(age);

Output:

0

For a non-null value:

String? ageText = '25';

final age = ageText.mapOr(
  (value) => int.parse(value),
  0,
);

print(age);

Output:

25

Lazy transformation fallback #

Use mapOrElse when the fallback result should be calculated only when needed.

String? value;

final result = value.mapOrElse(
  (value) => value.length,
  () => calculateDefaultLength(),
);

The fallback callback is not executed when value is non-null.


Execute only for non-null values #

Use runIfNotNull when you want to perform an action only when a value exists.

String? username = 'Sarvesh';

username.runIfNotNull(
  (value) {
    print('Hello $value');
  },
);

Output:

Hello Sarvesh

For a null value, the callback is not executed.


Execute only when null #

Use ifNull when you need to perform an action only when a value is missing.

String? profileImage;

profileImage.ifNull(() {
  print('Show default profile image');
});

First non-null value #

firstNotNull returns the first available non-null value.

final value = NullableUtils.firstNotNull<String>([
  null,
  null,
  'Flutter',
  'Dart',
]);

print(value);

Output:

Flutter

If every value is null, the result is null.

final value = NullableUtils.firstNotNull<String>([
  null,
  null,
  null,
]);

print(value);

Output:

null

First non-null value with fallback #

Use firstNotNullOr when you always need a non-null result.

final apiUrl = NullableUtils.firstNotNullOr<String>(
  [
    null,
    null,
    'https://example.com',
  ],
  'https://default.example.com',
);

print(apiUrl);

Null checks #

You can explicitly check nullable values using:

NullableUtils.isNull(value);

and:

NullableUtils.isNotNull(value);

Example:

String? username;

if (NullableUtils.isNull(username)) {
  print('Username is missing');
}

Or:

String? username = 'Sarvesh';

if (NullableUtils.isNotNull(username)) {
  print('Username is available');
}

Conditional values #

Use takeIf when a value should only be retained when a condition is true.

final result = NullableUtils.takeIf(
  'Flutter',
  true,
);

print(result);

Output:

Flutter

When the condition is false:

final result = NullableUtils.takeIf(
  'Flutter',
  false,
);

print(result);

Output:

null

Predicate-based selection #

Use takeIfOrNull when the condition depends on the value itself.

final result = NullableUtils.takeIfOrNull(
  100,
  (value) => value > 50,
);

print(result);

Output:

100

If the predicate fails:

final result = NullableUtils.takeIfOrNull(
  100,
  (value) => value > 200,
);

print(result);

Output:

null

Nullable filtering #

Use where to keep a nullable value only when it satisfies a predicate.

final result = NullableUtils.where(
  10,
  (value) => value.isEven,
);

print(result);

Output:

10

Example where the predicate fails:

final result = NullableUtils.where(
  11,
  (value) => value.isEven,
);

print(result);

Output:

null

The extension equivalent is:

final result = 10.where(
  (value) => value.isEven,
);

Conditional conversion #

Use convertIf when you want to transform a value only when a condition is satisfied.

final result = NullableUtils.convertIf(
  10,
  (value) => value > 5,
  (value) => 'Value: $value',
);

print(result);

Output:

Value: 10

If the condition fails, null is returned.


Fold nullable values #

fold lets you explicitly handle both cases.

String? username;

final message = username.fold(
  onValue: (value) => 'Welcome $value',
  onNull: () => 'Welcome Guest',
);

print(message);

Output:

Welcome Guest

With a value:

String? username = 'Sarvesh';

final message = username.fold(
  onValue: (value) => 'Welcome $value',
  onNull: () => 'Welcome Guest',
);

print(message);

Output:

Welcome Sarvesh

API Reference #

NullableUtils #

valueOr #

static T valueOr<T>(
  T? value,
  T fallback,
)

Returns value when non-null, otherwise returns fallback.


valueOrElse #

static T valueOrElse<T>(
  T? value,
  T Function() fallback,
)

Returns value when non-null, otherwise lazily evaluates fallback.


firstNotNull #

static T? firstNotNull<T>(
  Iterable<T?> values,
)

Returns the first non-null value.

Returns null when all values are null.


firstNotNullOr #

static T firstNotNullOr<T>(
  Iterable<T?> values,
  T fallback,
)

Returns the first non-null value or the supplied fallback.


isNull #

static bool isNull<T>(T? value)

Returns true when the value is null.


isNotNull #

static bool isNotNull<T>(T? value)

Returns true when the value is not null.


map #

static R? map<T, R>(
  T? value,
  R Function(T value) transform,
)

Transforms a non-null value and returns null for a null input.


mapOr #

static R mapOr<T, R>(
  T? value,
  R Function(T value) transform,
  R fallback,
)

Transforms a value or returns a fallback.


mapOrElse #

static R mapOrElse<T, R>(
  T? value,
  R Function(T value) transform,
  R Function() fallback,
)

Transforms a value or lazily computes a fallback.


runIfNotNull #

static T? runIfNotNull<T>(
  T? value,
  void Function(T value) action,
)

Runs an action only when the value is non-null.


ifNull #

static T? ifNull<T>(
  T? value,
  void Function() action,
)

Runs an action only when the value is null.


takeIf #

static T? takeIf<T>(
  T value,
  bool condition,
)

Returns the value when the condition is true.


takeIfOrNull #

static T? takeIfOrNull<T>(
  T value,
  bool Function(T value) predicate,
)

Returns the value when the predicate succeeds.


convertIf #

static R? convertIf<T, R>(
  T? value,
  bool Function(T value) condition,
  R Function(T value) convert,
)

Conditionally converts a nullable value.


let #

static R? let<T, R>(
  T? value,
  R? Function(T value) transform,
)

Applies a transformation only when the value is non-null.


where #

static T? where<T>(
  T? value,
  bool Function(T value) predicate,
)

Keeps a nullable value when the predicate succeeds.


nullable #

static T? nullable<T>(
  T? value,
)

Explicitly preserves a nullable value.


fold #

static R fold<T, R>(
  T? value, {
  required R Function(T value) onValue,
  required R Function() onNull,
})

Handles both nullable and non-null cases.


Extension API #

The package also provides:

extension NullableValueExtension<T> on T?

Available extension methods:

valueOr()
valueOrElse()
mapNullable()
mapOr()
mapOrElse()
runIfNotNull()
ifNull()
takeIf()
takeIfOrNull()
where()
fold()

This allows concise syntax such as:

final result = username
    .mapNullable((value) => value.trim())
    .mapOr(
      (value) => value.toUpperCase(),
      'UNKNOWN',
    );

Generic Usage #

The utilities work with custom types as well.

class User {
  final String name;

  const User(this.name);
}

You can write:

User? user;

final name = user.mapNullable(
  (value) => value.name,
);

Or:

final displayName = user.mapOr(
  (value) => value.name,
  'Guest',
);

No special model classes or wrappers are required.


Flutter Example #

The package can be useful inside Flutter widgets and ViewModels.

class ProfileViewModel {
  String? username;
  String? profileImage;

  String get displayName {
    return username.valueOr('Guest');
  }

  String get imageUrl {
    return profileImage.valueOr(
      'assets/images/default_profile.png',
    );
  }
}

Another example:

Text(
  user?.name.valueOr('Unknown') ?? 'Unknown',
)

For more complex transformations:

final displayName = user?.name.mapOr(
  (value) => value.trim().isEmpty
      ? 'Unknown'
      : value,
  'Unknown',
);

Design Philosophy #

zeba_academy_nullable is intentionally small.

The package does not introduce another nullable abstraction such as:

Option<T>
Some<T>
None<T>
Maybe<T>
Nullable<T>

Instead, it works directly with Dart's native:

T?

This keeps the package:

  • Simple
  • Familiar
  • Lightweight
  • Generic
  • Easy to adopt
  • Compatible with existing Dart code

For explicit Some/None style programming, a dedicated optional-value abstraction is more appropriate.


Dependencies #

This package has zero runtime dependencies.

It relies only on Dart's standard language and null-safety features.


Compatibility #

The package is designed for modern Dart and Flutter projects.

environment:
  sdk: ">=3.12.0 <4.0.0"
  flutter: ">=1.17.0"

Testing #

The package includes comprehensive unit tests covering:

  • Fallback values
  • Lazy fallbacks
  • Nullable transformations
  • Transformation fallbacks
  • Conditional execution
  • Null execution
  • First non-null selection
  • Conditional filtering
  • Conditional conversion
  • Fold operations
  • Extension methods
  • Generic behavior

Run the test suite with:

flutter test

Static Analysis #

Run:

flutter analyze

The package is intended to maintain a clean analyzer result before every release.


Formatting #

Format the package with:

dart format lib test

Publishing #

Before publishing to pub.dev, run:

flutter pub publish --dry-run

If everything is correct:

flutter pub publish

Contributing #

Contributions are welcome.

Before submitting a pull request:

  1. Keep APIs generic and null-safe.
  2. Avoid unnecessary dependencies.
  3. Add tests for new functionality.
  4. Run dart format.
  5. Run flutter analyze.
  6. Run flutter test.
  7. Update documentation when public APIs change.
  8. Keep the package focused on nullable-value utilities.

License #

This project is licensed under the GNU General Public License v3.0 (GPL-3.0).

See the LICENSE file for the complete license text.


About Me #

✨ I’m Sufyan bin Uzayr, an open-source developer passionate about building and sharing meaningful projects.

You can learn more about me and my work at sufyanism.com or connect with me on LinkedIn.


Your All-in-One Learning Hub! #

🚀 Explore courses and resources in coding, tech, and development at Zeba Academy.

Empower yourself with practical skills through curated tutorials, real-world projects, and hands-on experience. Level up your tech game today! 💻✨

Zeba Academy is a learning platform dedicated to coding, technology, and development.

➡ Visit the main site: zeba.academy

➡ Explore hands-on courses and resources: code.zeba.academy

➡ Check out the YouTube channel for more tutorials: Zeba Academy on YouTube

➡ Follow on Instagram: Zeba Academy on Instagram


Thank You #

Thank you for visiting and supporting this project! ❤️

If you find zeba_academy_nullable useful, consider giving the project a star, sharing it with other Dart and Flutter developers, and contributing to the open-source community.

Built with ❤️ for the Dart & Flutter community.

0
likes
150
points
56
downloads

Documentation

API reference

Publisher

verified publisherzeba.academy

Weekly Downloads

Generic nullable-value utilities for Dart and Flutter, including fallbacks, conditional mapping, null-safe execution, and transformations.

Homepage

License

GPL-3.0 (license)

Dependencies

flutter

More

Packages that depend on zeba_academy_nullable