Files
hans 221faa9c97
CI and Release / format (push) Successful in 34s
CI and Release / analyze (push) Successful in 26s
CI and Release / test (push) Successful in 48s
CI and Release / pana (push) Successful in 2m9s
CI and Release / version-and-changelog (push) Successful in 20s
CI and Release / publish (push) Failing after 13s
v1.0.0 - Initial release (#1)
Initial release 🥳

Reviewed-on: #1
2026-05-13 13:06:34 +02:00

90 lines
2.7 KiB
Markdown

# list_or
Ever worked with an API that usually returns a list of items, but sometimes decides to return a single item just to keep you on your toes?
`list_or` is a lightweight Dart utility that fixes this exact headache. It takes an arbitrary dynamic value, whether it's a single object, an array, a `Set`, or even `null`, and normalizes it into a standard, predictable `List<T>`.
No more writing boilerplate type-checks for every flexible JSON payload.
## Features
* **Normalizes inputs:** Wraps single values into a list, or passes through existing iterables.
* **Fully mutable:** Implements `ListMixin`, meaning you can `.add()`, `.map()`, `.remove()`, and iterate over it just like any other Dart list.
* **Type-safe:** Strictly enforces your generic type `T`. If you expect a `String` and get an `int`, it throws immediately.
* **Smart null handling:** Explicitly supports `null` values only if you define the type as nullable (e.g., `ListOr<String?>`).
* **Clean stringification:** If the list only has one item, `toString()` prints just that item instead of adding `[ ]` brackets.
## Getting Started
Add the package to your `pubspec.yaml`:
```bash
dart pub add list_or
```
Or, if you're using Flutter:
```bash
flutter pub add list_or
```
Import it in your file:
```dart
import 'package:list_or/list_or.dart';
```
## Usage
The most common use case is parsing unpredictable JSON.
Imagine an API endpoint where the `tags` field might be a single string or an array of strings depending on how many tags the user added.
```dart
import 'package:list_or/list_or.dart';
void main() {
// Scenario A: The API returns a single string
final Map<String, dynamic> json1 = {'id': 1, 'tags': 'flutter'};
// Scenario B: The API returns an array of strings
final Map<String, dynamic> json2 = {'id': 2, 'tags': ['dart', 'backend']};
// ListOr normalizes both seamlessly.
final tags1 = ListOr<String>(json1['tags']);
final tags2 = ListOr<String>(json2['tags']);
print(tags1); // Output: flutter
print(tags2); // Output: [dart, backend]
// You can interact with it exactly like a normal list
tags1.add('mobile');
print(tags1.length); // Output: 2
print(tags1.contains('mobile')); // Output: true
}
```
### Handling Nulls
If your payload might intentionally contain nulls, just make your generic type
nullable:
```dart
// This works perfectly
final nullableList = ListOr<int?>(null);
print(nullableList.length); // Output: 1
// This will throw an ArgumentError to keep your types safe
final strictList = ListOr<int>(null);
```
## Additional Information
* **Found a bug?** Open an issue on the issue tracker.
* **Want to contribute?** Pull requests are welcome. Please ensure that all existing tests pass and add new tests for any new functionality.