In Dart, check if a class inherits parent class with type checking

Viewed 1130

I am try to find a safe way to use Bloc patterns in Flutter with a very strong type checking.

Let's say we have this simple Bloc code:

// States 

abstract class CourseState {}

class CourseInitialized extends CourseState {}

// Events 

abstract class CourseEvent {}

class CourseFetch extends CourseEvent {}

class CourseLoaded extends CourseEvent {}

// Bloc (somewhere in the Bloc)

final event = CourseFetch();

In dart we can use the is operator to check if the event variable is of type CourseFetch or CourseEvent:

event is CourseFetch // true
event is CourseEvent // true

But nothing forbid me to check if event is of type CourseState or even of type a num, String, etc.

event is CourseInitialized // false
event is String // false

Of course is this case event can't be a String, because it has been initialized with CourseFetch() class.

I am try to find a way to forbid programmers (us) to wrongly write if statement that can never be evaluate to true.

In my case scenario I would like to have a way that stop me to check if a variable event of a certain type state in the IDE and give me a red squiggly line.

if (event is CourseInitialized) { 
// the above line should give me a warning, this variable event is not a State
}

Any ideas? Linting tools or syntax that can help?

UPDATE: I follow Rémi suggestion and try out Freezed, it makes the code simple and add up a safe type checking. Here you can find a complete implementation of Bloc with Freezed and Built Value.

1 Answers

There is no such thing (nor is it possible to know that you checked all the possible cases).

What you can instead do is replace the is operator with a function that does it for you.

One example of this is what the code-generator Freezed does.

Instead of:

abstract class CourseEvent {}

class CourseFetch extends CourseEvent {}

class CourseLoaded extends CourseEvent {}

You would write:

@freezed
abstract class CourseEvent with _$CourseEvent {
  factory CourseEvent.fetch() = _Fetch;
  factory CourseEvent.loaded() = _Loaded;
}

Which is then used as:

CourseEvent event;

event.when(
  fetch: () => print('Fetch event'),
  loaded: () => print('Loaded event'),
);
Related