Fix ObservableMap.cast/retype. (#64)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 88e1ba3..9636dfb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,10 @@
+## 0.22.0
+
+* Added `ObservableMap.castFrom`, similar to `Map.castFrom`.
+
+* Fixed a bug where `ObservableMap`'s `cast` and `retype` function would create
+  a new empty instance instead of a forwarding instance.
+
 ## 0.21.3
 
 * Support Dart 2 collection methods where previously threw `UnimplementedError`.
diff --git a/lib/src/observable_map.dart b/lib/src/observable_map.dart
index 4f43d13..b5c1f1b 100644
--- a/lib/src/observable_map.dart
+++ b/lib/src/observable_map.dart
@@ -20,6 +20,39 @@
 /// removed, or replaced, then observers that are listening to [changes]
 /// will be notified.
 class ObservableMap<K, V> extends Observable implements Map<K, V> {
+  /*
+     * Adapts [source] to be a `Map<K2, V2>`.
+   *
+   * Any time the set would produce a key or value that is not a [K2] or [V2],
+   * the access will throw.
+   *
+   * Any time [K2] key or [V2] value is attempted added into the adapted map,
+   * the store will throw unless the key is also an instance of [K] and
+   * the value is also an instance of [V].
+   *
+   * If all accessed entries of [source] are have [K2] keys and [V2] values
+   * and if all entries added to the returned map have [K] keys and [V]] values,
+   * then the returned map can be used as a `Map<K2, V2>`.
+   */
+
+  /// Adapts [source] to be a `ObservableMap<K2, V2>`.
+  ///
+  /// Any time the map would produce a key or value that is not a [K2] or [V2]
+  /// the access will throw.
+  ///
+  /// Any time [K2] key or [V2] value is attempted added into the adapted map,
+  /// the store will throw unless the key is also an instance of [K] and the
+  /// value is also an instance of [V].
+  ///
+  /// If all accessed entries of [source] have [K2] keys and [V2] values and if
+  /// all entries added to the returned map have [K] keys and [V] values, then
+  /// the returned map can be used as a `Map<K2, V2>`.
+  static ObservableMap<K2, V2> castFrom<K, V, K2, V2>(
+    ObservableMap<K, V> source,
+  ) {
+    return new ObservableMap<K2, V2>.spy(source._map.cast<K2, V2>());
+  }
+
   final Map<K, V> _map;
 
   /// Creates an observable map.
@@ -159,12 +192,12 @@
     if (this is ObservableMap<K2, V2>) {
       return this as ObservableMap<K2, V2>;
     }
-    return new ObservableMap.createFromType(_map.cast<K2, V2>());
+    return ObservableMap.castFrom<K, V, K2, V2>(this);
   }
 
   @override
   ObservableMap<K2, V2> retype<K2, V2>() {
-    return new ObservableMap.createFromType(_map.retype<K2, V2>());
+    return ObservableMap.castFrom<K, V, K2, V2>(this);
   }
 
   @override
diff --git a/pubspec.yaml b/pubspec.yaml
index 4f1b31d..0a67bfc 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
 name: observable
-version: 0.21.3
+version: 0.22.0
 author: Dart Team <misc@dartlang.org>
 description: Support for marking objects as observable
 homepage: https://github.com/dart-lang/observable