sealed class Option { const Option(); const factory Option.some(T value) = Some; const factory Option.none() = None; factory Option.fromNullable(T? value) => value != null ? Some(value) : None(); @pragma('vm:prefer-inline') bool get isSome => this is Some; @pragma('vm:prefer-inline') bool get isNone => this is None; @pragma('vm:prefer-inline') T? get unwrapOrNull => switch (this) { Some(:final value) => value, None() => null, }; U fold(U Function(T value) onSome, U Function() onNone) => switch (this) { Some(:final value) => onSome(value), None() => onNone(), }; @override String toString() => switch (this) { Some(:final value) => 'Some($value)', None() => 'None', }; } final class Some extends Option { final T value; const Some(this.value); @override bool operator ==(Object other) => other is Some && other.value == value; @override int get hashCode => value.hashCode; } final class None extends Option { const None(); @override bool operator ==(Object other) => other is None; @override int get hashCode => 0; } extension ObjectOptionExtension on T? { Option toOption() => Option.fromNullable(this); }