Package selection guidance compiled from public package information, community data, and project usage.
Equatable is a Dart package that simplifies implementing value-based equality by automatically generating == and hashCode methods based on an object's properties. It eliminates the need to manually override these methods, reducing boilerplate code and minimizing errors. Ideal for models, states, and any class where equality depends on field values rather than identity. The package integrates seamlessly with Flutter and other Dart projects, enhancing code readability and maintainability.
Use cases
Comparing model objects in state management
Simplifying equality checks in Redux or Bloc patterns
Reducing boilerplate in data classes
Validating state changes in reactive UIs
Ensuring consistent hashing in collections
Key features
Automatic == and hashCode generation
Minimal boilerplate
Support for nested and complex types
Easy integration with Flutter state management
Extensible through mixins
Suitable for
Developers using Bloc or Redux
Teams prioritizing clean, maintainable code
Projects with frequent data comparison needs
Dart developers avoiding manual equality logic
Applications requiring predictable state updates
Considerations
May increase build time slightly
Not suitable for reference-based equality
Requires careful handling of null values
Limited customization for complex equality rules
Best used with immutable data structures
Original README
Original README snapshot from the linked source repository. Visit the repository for the latest content.
Simplify Equality Comparisons
Overview
Being able to compare objects in Dart often involves having to override the == operator as well as hashCode.
Not only is it verbose and tedious, but failure to do so can lead to inefficient code which does not behave as we expect.
By default, == returns true if two objects are the same instance.
it will be able to compare different instances of Person.
You can see how this can quickly become a hassle when dealing with complex classes. This is where Equatable comes in!
What does Equatable do?
Equatable overrides == and hashCode for you so you don't have to waste your time writing lots of boilerplate code.
There are other packages that will actually generate the boilerplate for you; however, you still have to run the code generation step which is not ideal.
With Equatable there is no code generation needed and we can focus more on writing amazing applications and less on mundane tasks.
Usage
First, we need to do add equatable to the dependencies of the pubspec.yaml
dependencies:equatable:^3.0.0
Next, we need to install it:
# Dart
dart pub get
# Flutter
flutter packages get
We can now compare instances of Person just like before without the pain of having to write all of that boilerplate.
Note: Equatable is designed to only work with immutable objects so all member variables must be final (This is not just a feature of Equatable - overriding a hashCode with a mutable value can break hash-based collections).
Equatable can implement toString method including all the given props. If you want that behaviour for a specific Equatable object, just include the following:
This flag by default is false and toString will fallback to the default implementation:
Instance of Person
EquatableConfig
stringify can also be configured globally for all Equatable instances via EquatableConfig
EquatableConfig.stringify = true;
If stringify is overridden for a specific Equatable class, then the value of EquatableConfig.stringify is ignored.
In other words, the local configuration always takes precedence over the global configuration.
Note: EquatableConfig.stringify defaults to true in debug mode and false in release mode.
Sometimes it isn't possible to extend Equatable because your class already has a superclass.
In this case, you can still get the benefits of Equatable by using Equatable as a mixin.
Usage
Let's say we want to make an EquatableDateTime class, we can use Equatable like so:
classEquatableDateTimeextendsDateTimewithEquatable{
EquatableDateTime(
int year, [
int month = 1,
int day = 1,
int hour = 0,
int minute = 0,
int second = 0,
int millisecond = 0,
int microsecond = 0,
]) : super(year, month, day, hour, minute, second, millisecond, microsecond);
@overrideList<Object> get props {
return [year, month, day, hour, minute, second, millisecond, microsecond];
}
}
Now if we want to create a subclass of EquatableDateTime, we can just override props.
classEquatableDateTimeSubclassextendsEquatableDateTime{
finalint century;
EquatableDateTimeSubclass(
this.century,
int year,[
int month = 1,
int day = 1,
int hour = 0,
int minute = 0,
int second = 0,
int millisecond = 0,
int microsecond = 0,
]) : super(year, month, day, hour, minute, second, millisecond, microsecond);
@overrideList<Object> get props => [...super.props, century];
}
Benchmarks
You can see and run performance benchmarks by heading over to benchmarks.