Add toObservableList and toObservableMap (#81)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6969548..db46b07 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+## HEAD
+
+* Add `toObservableList` and `toObservableMap`, better typed versions of
+ `toObservable`.
+
## 0.22.1+5
Fix generic type error that occurs when using ChangeNotifier with a subclass of
diff --git a/lib/src/to_observable.dart b/lib/src/to_observable.dart
index d331913..20f8d7e 100644
--- a/lib/src/to_observable.dart
+++ b/lib/src/to_observable.dart
@@ -16,6 +16,9 @@
/// respectively. This is a convenience function to make it easier to convert
/// literals into the corresponding observable collection type.
///
+/// For better static typing, use either [toObservableList] or
+/// [toObservableMap] instead of this function.
+///
/// If [value] is not one of those collection types, or is already [Observable],
/// it will be returned unmodified.
///
@@ -30,6 +33,35 @@
toObservable(dynamic value, {bool deep = true}) =>
deep ? _toObservableDeep(value) : _toObservableShallow(value);
+/// Converts the [Iterable] to an [ObservableList].
+///
+/// If [value] is already [Observable], it will be returned unmodified.
+///
+/// By default this performs a deep conversion, but you can set [deep] to false
+/// for a shallow conversion. This does not handle circular data structures.
+/// If a conversion is peformed, mutations are only observed to the result of
+/// this function. Changing the original collection will not affect it.
+ObservableList<T> toObservableList<T>(Iterable<T> value, {bool deep: true}) {
+ if (value is Observable) return value;
+ return deep ? _toObservableDeepIterable(value) : _toObservableShallow(value);
+}
+
+/// Converts the [Map] to an [ObservableMap].
+///
+/// If [value] is already [Observable], it will be returned unmodified.
+///
+/// The returned value will use the appropriate kind of backing map: either
+/// [HashMap], [LinkedHashMap], or [SplayTreeMap].
+///
+/// By default this performs a deep conversion, but you can set [deep] to false
+/// for a shallow conversion. This does not handle circular data structures.
+/// If a conversion is peformed, mutations are only observed to the result of
+/// this function. Changing the original collection will not affect it.
+ObservableMap<K, V> toObservableMap<K, V>(Map<K, V> value, {bool deep: true}) {
+ if (value is Observable) return value;
+ return deep ? _toObservableDeepMap(value) : _toObservableShallow(value);
+}
+
dynamic _toObservableShallow(dynamic value) {
if (value is Observable) return value;
@@ -49,25 +81,29 @@
dynamic _toObservableDeep(dynamic value) {
if (value is Observable) return value;
- if (value is Map) {
- return extractMapTypeArguments(value, <K, V>() {
- var result = new ObservableMap<K, V>.createFromType(value);
- value.forEach((k, v) {
- result[_toObservableDeep(k)] = _toObservableDeep(v);
- });
- return result;
- });
- }
+ if (value is Map) return _toObservableDeepMap(value);
- if (value is Iterable) {
- return extractIterableTypeArgument(value, <T>() {
- var result = new ObservableList<T>();
- for (var element in value) {
- result.add(_toObservableDeep(element));
- }
- return result;
- });
- }
+ if (value is Iterable) return _toObservableDeepIterable(value);
return value;
}
+
+ObservableMap _toObservableDeepMap(Map<dynamic, dynamic> value) {
+ return extractMapTypeArguments(value, <K, V>() {
+ var result = new ObservableMap<K, V>.createFromType(value);
+ value.forEach((k, v) {
+ result[_toObservableDeep(k)] = _toObservableDeep(v);
+ });
+ return result;
+ });
+}
+
+ObservableList _toObservableDeepIterable(Iterable<dynamic> value) {
+ return extractIterableTypeArgument(value, <T>() {
+ var result = new ObservableList<T>();
+ for (var element in value) {
+ result.add(_toObservableDeep(element));
+ }
+ return result;
+ });
+}