diff --git a/.travis.yml b/.travis.yml
index 7aae45cf470b3da56cc79a2bdde72a649bbc7439..2ed895fc64c5997fb01d9f01780684af1a62e9e7 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,7 +2,7 @@ language: dart
 sudo: required
 
 dart:
- - dev
+ - 2.0.0-dev.60.0
 
 env: FORCE_TEST_EXIT=true
 
diff --git a/lib/src/backend/declarer.dart b/lib/src/backend/declarer.dart
index 3e1791689a2b1d00742b6982cce8a306d35a6ad1..d3e11fa8e776bba82ecc8c8fff6e2b54a5325267 100644
--- a/lib/src/backend/declarer.dart
+++ b/lib/src/backend/declarer.dart
@@ -81,7 +81,7 @@ class Declarer {
   bool _built = false;
 
   /// The current zone-scoped declarer.
-  static Declarer get current => Zone.current[#test.declarer];
+  static Declarer get current => Zone.current[#test.declarer] as Declarer;
 
   /// Creates a new declarer for the root group.
   ///
diff --git a/lib/src/backend/invoker.dart b/lib/src/backend/invoker.dart
index 5aefef68230dddabac15e94594bc567b08e3c7e3..59e0907355cdb6b50a062b5dda5f08df0901ca00 100644
--- a/lib/src/backend/invoker.dart
+++ b/lib/src/backend/invoker.dart
@@ -79,7 +79,7 @@ class Invoker {
   final bool _guarded;
 
   /// Whether the test can be closed in the current zone.
-  bool get _closable => Zone.current[_closableKey];
+  bool get _closable => Zone.current[_closableKey] as bool;
 
   /// An opaque object used as a key in the zone value map to identify
   /// [_closable].
@@ -108,7 +108,7 @@ class Invoker {
 
   /// The outstanding callback counter for the current zone.
   OutstandingCallbackCounter get _outstandingCallbacks {
-    var counter = Zone.current[_counterKey];
+    var counter = Zone.current[_counterKey] as OutstandingCallbackCounter;
     if (counter != null) return counter;
     throw new StateError("Can't add or remove outstanding callbacks outside "
         "of a test body.");
@@ -135,7 +135,7 @@ class Invoker {
   /// An invoker is only set within the zone scope of a running test.
   static Invoker get current {
     // TODO(nweiz): Use a private symbol when dart2js supports it (issue 17526).
-    return Zone.current[#test.invoker];
+    return Zone.current[#test.invoker] as Invoker;
   }
 
   /// Runs [callback] in a zone where unhandled errors from [LiveTest]s are
@@ -241,7 +241,7 @@ class Invoker {
   Future waitForOutstandingCallbacks(fn()) {
     heartbeat();
 
-    var zone;
+    Zone zone;
     var counter = new OutstandingCallbackCounter();
     runZoned(() async {
       zone = Zone.current;
diff --git a/lib/src/backend/metadata.dart b/lib/src/backend/metadata.dart
index 83929b653c0de1e14e6b2b8895e0c4f911e744df..5aa28ebd894f8b49e1322d77d975667defa6d6d7 100644
--- a/lib/src/backend/metadata.dart
+++ b/lib/src/backend/metadata.dart
@@ -84,8 +84,8 @@ class Metadata {
 
       var selector = new PlatformSelector.parse(platform);
 
-      var timeout;
-      var skip;
+      Timeout timeout;
+      dynamic skip;
       for (var metadatum in metadata) {
         if (metadatum is Timeout) {
           if (timeout != null) {
@@ -123,11 +123,11 @@ class Metadata {
           tags, "tags", "must be either a String or an Iterable.");
     }
 
-    if (tags.any((tag) => tag is! String)) {
+    if ((tags as Iterable).any((tag) => tag is! String)) {
       throw new ArgumentError.value(tags, "tags", "must contain only Strings.");
     }
 
-    return new Set.from(tags);
+    return new Set.from(tags as Iterable);
   }
 
   /// Creates new Metadata.
@@ -171,7 +171,7 @@ class Metadata {
     // we only have to resolve suite- or group-level tags once, rather than
     // doing it for every test individually.
     var empty = new Metadata._();
-    var merged = forTag.keys.toList().fold(empty, (merged, selector) {
+    var merged = forTag.keys.toList().fold(empty, (Metadata merged, selector) {
       if (!selector.evaluate(tags)) return merged;
       return merged.merge(forTag.remove(selector));
     });
@@ -215,7 +215,7 @@ class Metadata {
   Metadata.parse(
       {String testOn,
       Timeout timeout,
-      skip,
+      dynamic skip,
       bool verboseTrace,
       bool chainStackTraces,
       int retry,
@@ -247,27 +247,28 @@ class Metadata {
   Metadata.deserialize(serialized)
       : testOn = serialized['testOn'] == null
             ? PlatformSelector.all
-            : new PlatformSelector.parse(serialized['testOn']),
+            : new PlatformSelector.parse(serialized['testOn'] as String),
         timeout = _deserializeTimeout(serialized['timeout']),
-        _skip = serialized['skip'],
-        skipReason = serialized['skipReason'],
-        _verboseTrace = serialized['verboseTrace'],
-        _chainStackTraces = serialized['chainStackTraces'],
-        _retry = serialized['retry'],
-        tags = new Set.from(serialized['tags']),
-        onPlatform = new Map.fromIterable(serialized['onPlatform'],
-            key: (pair) => new PlatformSelector.parse(pair.first),
+        _skip = serialized['skip'] as bool,
+        skipReason = serialized['skipReason'] as String,
+        _verboseTrace = serialized['verboseTrace'] as bool,
+        _chainStackTraces = serialized['chainStackTraces'] as bool,
+        _retry = serialized['retry'] as int,
+        tags = new Set.from(serialized['tags'] as Iterable),
+        onPlatform = new Map.fromIterable(serialized['onPlatform'] as Iterable,
+            key: (pair) => new PlatformSelector.parse(pair.first as String),
             value: (pair) => new Metadata.deserialize(pair.last)),
-        forTag = mapMap(serialized['forTag'],
-            key: (key, _) => new BooleanSelector.parse(key),
-            value: (_, nested) => new Metadata.deserialize(nested));
+        forTag = (serialized['forTag'] as Map).map((key, nested) =>
+            new MapEntry(new BooleanSelector.parse(key as String),
+                new Metadata.deserialize(nested)));
 
   /// Deserializes timeout from the format returned by [_serializeTimeout].
-  static _deserializeTimeout(serialized) {
+  static Timeout _deserializeTimeout(serialized) {
     if (serialized == 'none') return Timeout.none;
     var scaleFactor = serialized['scaleFactor'];
-    if (scaleFactor != null) return new Timeout.factor(scaleFactor);
-    return new Timeout(new Duration(microseconds: serialized['duration']));
+    if (scaleFactor != null) return new Timeout.factor(scaleFactor as num);
+    return new Timeout(
+        new Duration(microseconds: serialized['duration'] as int));
   }
 
   /// Throws an [ArgumentError] if any tags in [tags] aren't hyphenated
@@ -382,9 +383,8 @@ class Metadata {
       'retry': _retry,
       'tags': tags.toList(),
       'onPlatform': serializedOnPlatform,
-      'forTag': mapMap(forTag,
-          key: (selector, _) => selector.toString(),
-          value: (_, metadata) => metadata.serialize())
+      'forTag': forTag.map((selector, metadata) =>
+          new MapEntry(selector.toString(), metadata.serialize()))
     };
   }
 
diff --git a/lib/src/backend/platform_selector.dart b/lib/src/backend/platform_selector.dart
index 35b063dd78fc12cc17e52a9f4c531a6e035afd38..b0acc3f2ab69991e291a7cb89f3c61393b14b0da 100644
--- a/lib/src/backend/platform_selector.dart
+++ b/lib/src/backend/platform_selector.dart
@@ -73,7 +73,7 @@ class PlatformSelector {
   ///
   /// [os] defaults to [OperatingSystem.none].
   bool evaluate(SuitePlatform platform) {
-    return _inner.evaluate((variable) {
+    return _inner.evaluate((String variable) {
       if (variable == platform.runtime.identifier) return true;
       if (variable == platform.runtime.parent?.identifier) return true;
       if (variable == platform.os.identifier) return true;
diff --git a/lib/src/backend/runtime.dart b/lib/src/backend/runtime.dart
index f6a51e8bcf409696d817b6ba51a7171e33ae8200..d261b4d433ca9d0d0851fb2221214e09ae53fc52 100644
--- a/lib/src/backend/runtime.dart
+++ b/lib/src/backend/runtime.dart
@@ -108,16 +108,16 @@ class Runtime {
       // a separately-deserialized parent platform. This should be fine, though,
       // since we only deserialize platforms in the remote execution context
       // where they're only used to evaluate platform selectors.
-      return new Runtime._child(
-          map["name"], map["identifier"], new Runtime.deserialize(parent));
+      return new Runtime._child(map["name"] as String,
+          map["identifier"] as String, new Runtime.deserialize(parent));
     }
 
-    return new Runtime(map["name"], map["identifier"],
-        isDartVM: map["isDartVM"],
-        isBrowser: map["isBrowser"],
-        isJS: map["isJS"],
-        isBlink: map["isBlink"],
-        isHeadless: map["isHeadless"]);
+    return new Runtime(map["name"] as String, map["identifier"] as String,
+        isDartVM: map["isDartVM"] as bool,
+        isBrowser: map["isBrowser"] as bool,
+        isJS: map["isJS"] as bool,
+        isBlink: map["isBlink"] as bool,
+        isHeadless: map["isHeadless"] as bool);
   }
 
   /// Converts [this] into a JSON-safe object that can be converted back to a
diff --git a/lib/src/backend/suite_platform.dart b/lib/src/backend/suite_platform.dart
index b0f59e1fe6a28c478faa75e3001258d9082aa326..554423a896e49f473757ecd9c61aefa6dba5f5d5 100644
--- a/lib/src/backend/suite_platform.dart
+++ b/lib/src/backend/suite_platform.dart
@@ -36,7 +36,8 @@ class SuitePlatform {
   factory SuitePlatform.deserialize(Object serialized) {
     var map = serialized as Map;
     return new SuitePlatform(new Runtime.deserialize(map['runtime']),
-        os: OperatingSystem.find(map['os']), inGoogle: map['inGoogle']);
+        os: OperatingSystem.find(map['os'] as String),
+        inGoogle: map['inGoogle'] as bool);
   }
 
   /// Converts [this] into a JSON-safe object that can be converted back to a
diff --git a/lib/src/bootstrap/browser.dart b/lib/src/bootstrap/browser.dart
index a802be2d45306b88d2a7f3a0ac322489309561a0..2ba84ce67c6c415126cd9e3a7eb43e2d2a0a9daf 100644
--- a/lib/src/bootstrap/browser.dart
+++ b/lib/src/bootstrap/browser.dart
@@ -13,7 +13,8 @@ import "../util/stack_trace_mapper.dart";
 void internalBootstrapBrowserTest(Function getMain()) {
   var channel =
       serializeSuite(getMain, hidePrints: false, beforeLoad: () async {
-    var serialized = await suiteChannel("test.browser.mapper").stream.first;
+    var serialized =
+        await suiteChannel("test.browser.mapper").stream.first as Map;
     if (serialized == null) return;
     setStackTraceMapper(StackTraceMapper.deserialize(serialized));
   });
diff --git a/lib/src/bootstrap/node.dart b/lib/src/bootstrap/node.dart
index 672abe2ca0e08019c644f2a72d36edb9ccf90701..bf9a9b3d068ce6ada75ae1ecff782ab5bfb368ab 100644
--- a/lib/src/bootstrap/node.dart
+++ b/lib/src/bootstrap/node.dart
@@ -14,7 +14,7 @@ void internalBootstrapNodeTest(Function getMain()) {
   var channel = serializeSuite(getMain, beforeLoad: () async {
     var serialized = await suiteChannel("test.node.mapper").stream.first;
     if (serialized == null || serialized is! Map) return;
-    setStackTraceMapper(StackTraceMapper.deserialize(serialized));
+    setStackTraceMapper(StackTraceMapper.deserialize(serialized as Map));
   });
   socketChannel().pipe(channel);
 }
diff --git a/lib/src/executable.dart b/lib/src/executable.dart
index 7616371e4fd2c3108b775a412fef362a274ceb22..ca544464cb47ef9ce7168539943742a51ec668b6 100644
--- a/lib/src/executable.dart
+++ b/lib/src/executable.dart
@@ -51,7 +51,7 @@ bool get _usesTransformer {
   if (transformers == null) return false;
   if (transformers is! List) return false;
 
-  return transformers.any((transformer) {
+  return (transformers as List).any((transformer) {
     if (transformer is String) return transformer == 'test/pub_serve';
     if (transformer is! Map) return false;
     if (transformer.keys.length != 1) return false;
diff --git a/lib/src/frontend/async_matcher.dart b/lib/src/frontend/async_matcher.dart
index 23ec862afefde9f716722956859de60934616bc6..2a4ceabf66debb866d8275348e42d0d5c1bf0f07 100644
--- a/lib/src/frontend/async_matcher.dart
+++ b/lib/src/frontend/async_matcher.dart
@@ -43,8 +43,10 @@ abstract class AsyncMatcher extends Matcher {
     if (result is Future) {
       Invoker.current.addOutstandingCallback();
       result.then((realResult) {
-        // ignore: deprecated_member_use
-        if (realResult != null) fail(formatFailure(this, item, realResult));
+        if (realResult != null) {
+          // ignore: deprecated_member_use
+          fail(formatFailure(this, item, realResult as String));
+        }
         Invoker.current.removeOutstandingCallback();
       });
     } else if (result is String) {
@@ -57,5 +59,5 @@ abstract class AsyncMatcher extends Matcher {
 
   Description describeMismatch(
           item, Description description, Map matchState, bool verbose) =>
-      new StringDescription(matchState[this]);
+      new StringDescription(matchState[this] as String);
 }
diff --git a/lib/src/frontend/expect.dart b/lib/src/frontend/expect.dart
index 7edaffc0c5ab76f154eb0b706516558714a35e00..0f7f0ab17a7f3c84afc12af1d9940f3a0175691b 100644
--- a/lib/src/frontend/expect.dart
+++ b/lib/src/frontend/expect.dart
@@ -131,13 +131,14 @@ Future _expect(actual, matcher,
 
     if (result is String) {
       // ignore: deprecated_member_use
-      fail(formatFailure(matcher, actual, result, reason: reason));
+      fail(formatFailure(matcher as Matcher, actual, result, reason: reason));
     } else if (result is Future) {
       Invoker.current.addOutstandingCallback();
       return result.then((realResult) {
         if (realResult == null) return;
         // ignore: deprecated_member_use
-        fail(formatFailure(matcher, actual, realResult, reason: reason));
+        fail(formatFailure(matcher as Matcher, actual, realResult as String,
+            reason: reason));
       }).whenComplete(() {
         // Always remove this, in case the failure is caught and handled
         // gracefully.
@@ -150,11 +151,12 @@ Future _expect(actual, matcher,
 
   var matchState = {};
   try {
-    if (matcher.matches(actual, matchState)) return new Future.sync(() {});
+    if ((matcher as Matcher).matches(actual, matchState))
+      return new Future.sync(() {});
   } catch (e, trace) {
     reason ??= '$e at $trace';
   }
-  fail(formatter(actual, matcher, reason, matchState, verbose));
+  fail(formatter(actual, matcher as Matcher, reason, matchState, verbose));
 }
 
 /// Convenience method for throwing a new [TestFailure] with the provided
diff --git a/lib/src/frontend/expect_async.dart b/lib/src/frontend/expect_async.dart
index 9e5727cd5f2fac701cba388504f24c04a8e9adc1..31cac0fa6fe93b774f8fb4a06e6a0868410ac595 100644
--- a/lib/src/frontend/expect_async.dart
+++ b/lib/src/frontend/expect_async.dart
@@ -76,7 +76,7 @@ class _ExpectedFunction<T> {
   int _actualCalls = 0;
 
   /// The test invoker in which this function was wrapped.
-  Invoker get _invoker => _zone[#test.invoker];
+  Invoker get _invoker => _zone[#test.invoker] as Invoker;
 
   /// The zone in which this function was wrapped.
   final Zone _zone;
diff --git a/lib/src/frontend/future_matchers.dart b/lib/src/frontend/future_matchers.dart
index 29be5280c45100da98a51fbbd2fb066ce7dcd72e..19330e6521af6f287228bc1741c7ff042544943c 100644
--- a/lib/src/frontend/future_matchers.dart
+++ b/lib/src/frontend/future_matchers.dart
@@ -53,7 +53,7 @@ class _Completes extends AsyncMatcher {
 
       String result;
       if (_matcher is AsyncMatcher) {
-        result = await (_matcher as AsyncMatcher).matchAsync(value);
+        result = await (_matcher as AsyncMatcher).matchAsync(value) as String;
         if (result == null) return null;
       } else {
         var matchState = {};
diff --git a/lib/src/frontend/prints_matcher.dart b/lib/src/frontend/prints_matcher.dart
index 421425fe2711ee7dd4c6fadd69a4d2d17c04ff4a..20a92bc4aa5d1e8144d209c168108ab91e94e506 100644
--- a/lib/src/frontend/prints_matcher.dart
+++ b/lib/src/frontend/prints_matcher.dart
@@ -31,10 +31,10 @@ class _Prints extends AsyncMatcher {
   // Avoid async/await so we synchronously fail if the function is
   // synchronous.
   /*FutureOr<String>*/ matchAsync(item) {
-    if (item is! Function) return "was not a Function";
+    if (item is! Function()) return "was not a unary Function";
 
     var buffer = new StringBuffer();
-    var result = runZoned(item,
+    var result = runZoned(item as Function(),
         zoneSpecification: new ZoneSpecification(print: (_, __, ____, line) {
       buffer.writeln(line);
     }));
diff --git a/lib/src/frontend/spawn_hybrid.dart b/lib/src/frontend/spawn_hybrid.dart
index ff6998fb671be34ac0484cad52fd377c3d628072..47a5ad53cfce4f1d6d3a77086894719d70e1a268 100644
--- a/lib/src/frontend/spawn_hybrid.dart
+++ b/lib/src/frontend/spawn_hybrid.dart
@@ -23,7 +23,7 @@ import '../utils.dart';
 // TODO(grouma) - Restore the type here and correctly flow it throughout.
 final _transformer = new StreamChannelTransformer<dynamic, dynamic>(
     new StreamTransformer.fromHandlers(handleData: (message, sink) {
-  switch (message["type"]) {
+  switch (message["type"] as String) {
     case "data":
       sink.add(message["data"]);
       break;
diff --git a/lib/src/frontend/stream_matchers.dart b/lib/src/frontend/stream_matchers.dart
index cc6a3aa490f4de7d5711a56d5a2656838df225e2..dfac04bb264ee71358a0930042c722133f218c86 100644
--- a/lib/src/frontend/stream_matchers.dart
+++ b/lib/src/frontend/stream_matchers.dart
@@ -56,7 +56,7 @@ StreamMatcher emitsError(matcher) {
   var throwsMatcher = throwsA(wrapped) as AsyncMatcher;
 
   return new StreamMatcher(
-      (queue) => throwsMatcher.matchAsync(queue.next),
+      (queue) => throwsMatcher.matchAsync(queue.next) as Future<String>,
       // TODO(nweiz): add "should" once matcher#42 is fixed.
       "emit an error that $matcherDescription");
 }
diff --git a/lib/src/runner.dart b/lib/src/runner.dart
index 02e6bef01ec2f7d2f9f109ef1c8e3436a8e6de7b..ff7d92b91b7d0814ed4d210686d19c68536985eb 100644
--- a/lib/src/runner.dart
+++ b/lib/src/runner.dart
@@ -299,7 +299,7 @@ class Runner {
     var unknownTags = <String, List<GroupEntry>>{};
     var currentTags = new Set<String>();
 
-    collect(entry) {
+    collect(GroupEntry entry) {
       var newTags = new Set<String>();
       for (var unknownTag
           in entry.metadata.tags.difference(_config.knownTags)) {
@@ -309,9 +309,10 @@ class Runner {
       }
 
       if (entry is! Group) return;
+      var group = entry as Group;
 
       currentTags.addAll(newTags);
-      for (var child in entry.entries) {
+      for (var child in group.entries) {
         collect(child);
       }
       currentTags.removeAll(newTags);
@@ -335,7 +336,7 @@ class Runner {
   /// index. This makes the tests pretty tests across shards, and since the
   /// tests are continuous, makes us more likely to be able to re-use
   /// `setUpAll()` logic.
-  Suite _shardSuite(Suite suite) {
+  T _shardSuite<T extends Suite>(T suite) {
     if (_config.totalShards == null) return suite;
 
     var shardSize = suite.group.testCount / _config.totalShards;
@@ -348,7 +349,7 @@ class Runner {
       return count >= shardStart && count < shardEnd;
     });
 
-    return filtered;
+    return filtered as T;
   }
 
   /// Loads each suite in [suites] in order, pausing after load for runtimes
@@ -368,6 +369,6 @@ class Runner {
       _suiteSubscription.asFuture().then((_) => _engine.suiteSink.close()),
       _engine.run()
     ], eagerError: true);
-    return results.last;
+    return results.last as bool;
   }
 }
diff --git a/lib/src/runner/browser/browser.dart b/lib/src/runner/browser/browser.dart
index 2f769de6246cd68fe4d3b94d5d6c58f2b22ea6a7..c158a8b05c2e50661624e29db83b85d4147cd43d 100644
--- a/lib/src/runner/browser/browser.dart
+++ b/lib/src/runner/browser/browser.dart
@@ -107,7 +107,7 @@ abstract class Browser {
       }
 
       _onExitCompleter.complete();
-    }, onError: (error, stackTrace) {
+    }, onError: (error, StackTrace stackTrace) {
       // Ignore any errors after the browser has been closed.
       if (_closed) return;
 
diff --git a/lib/src/runner/browser/browser_manager.dart b/lib/src/runner/browser/browser_manager.dart
index 52922c97c02fc77d63a73eb93ae8232111e313cb..75778c4527427c24fe06c9b245b2c80e2c9a4311 100644
--- a/lib/src/runner/browser/browser_manager.dart
+++ b/lib/src/runner/browser/browser_manager.dart
@@ -109,7 +109,7 @@ class BrowserManager {
     browser.onExit.then((_) {
       throw new ApplicationException(
           "${runtime.name} exited before connecting.");
-    }).catchError((error, stackTrace) {
+    }).catchError((error, StackTrace stackTrace) {
       if (completer.isCompleted) return;
       completer.completeError(error, stackTrace);
     });
@@ -117,7 +117,7 @@ class BrowserManager {
     future.then((webSocket) {
       if (completer.isCompleted) return;
       completer.complete(new BrowserManager._(browser, runtime, webSocket));
-    }).catchError((error, stackTrace) {
+    }).catchError((error, StackTrace stackTrace) {
       browser.close();
       if (completer.isCompleted) return;
       completer.completeError(error, stackTrace);
@@ -183,7 +183,8 @@ class BrowserManager {
     }));
 
     _environment = _loadBrowserEnvironment();
-    _channel.stream.listen((message) => _onMessage(message), onDone: close);
+    _channel.stream
+        .listen((message) => _onMessage(message as Map), onDone: close);
   }
 
   /// Loads [_BrowserEnvironment].
@@ -210,7 +211,7 @@ class BrowserManager {
     })));
 
     var suiteID = _suiteID++;
-    var controller;
+    RunnerSuiteController controller;
     closeIframe() {
       if (_closed) return;
       _controllers.remove(controller);
@@ -270,7 +271,7 @@ class BrowserManager {
 
   /// The callback for handling messages received from the host page.
   void _onMessage(Map message) {
-    switch (message["command"]) {
+    switch (message["command"] as String) {
       case "ping":
         break;
 
diff --git a/lib/src/runner/browser/platform.dart b/lib/src/runner/browser/platform.dart
index 2f26dfd241256a85b8b3fa92b6833047d9b49f50..918ba1b3865d5390a33ce8116a51cff3941ce296 100644
--- a/lib/src/runner/browser/platform.dart
+++ b/lib/src/runner/browser/platform.dart
@@ -232,7 +232,7 @@ class BrowserPlatform extends PlatformPlugin
           '</script>.');
     }
 
-    var suiteUrl;
+    Uri suiteUrl;
     if (_config.pubServeUrl != null) {
       var suitePrefix = p
           .toUri(
diff --git a/lib/src/runner/compiler_pool.dart b/lib/src/runner/compiler_pool.dart
index 305b1949aa97ce0bc061cb9e70349b0ae5d0d057..506aefa4d49b18e7637bc8cf6b8dcd4d551d750e 100644
--- a/lib/src/runner/compiler_pool.dart
+++ b/lib/src/runner/compiler_pool.dart
@@ -113,9 +113,9 @@ class CompilerPool {
   /// URIs that are resolvable by the browser.
   void _fixSourceMap(String mapPath) {
     var map = jsonDecode(new File(mapPath).readAsStringSync());
-    var root = map['sourceRoot'];
+    var root = map['sourceRoot'] as String;
 
-    map['sources'] = map['sources'].map((source) {
+    map['sources'] = map['sources'].map((String source) {
       var url = Uri.parse(root + source);
       if (url.scheme != '' && url.scheme != 'file') return source;
       if (url.path.endsWith("/runInBrowser.dart")) return "";
diff --git a/lib/src/runner/configuration.dart b/lib/src/runner/configuration.dart
index 2e3563c02f756a4b881f545f3d6602da64c6afaf..1ca4419042c8f8689cddaff7f8ee5f3aabd11108 100644
--- a/lib/src/runner/configuration.dart
+++ b/lib/src/runner/configuration.dart
@@ -188,7 +188,7 @@ class Configuration {
   ///
   /// The current configuration is set using [asCurrent].
   static Configuration get current =>
-      Zone.current[_currentKey] ?? new Configuration();
+      Zone.current[_currentKey] as Configuration ?? new Configuration();
 
   /// Parses the configuration from [args].
   ///
@@ -294,12 +294,13 @@ class Configuration {
     return configuration._resolvePresets();
   }
 
-  static Map<Object, Configuration> _withChosenPresets(
-      Map<Object, Configuration> map, Set<String> chosenPresets) {
+  static Map<String, Configuration> _withChosenPresets(
+      Map<String, Configuration> map, Set<String> chosenPresets) {
     if (map == null || chosenPresets == null) return map;
-    return mapMap(map,
-        value: (_, config) => config.change(
-            chosenPresets: config.chosenPresets.union(chosenPresets)));
+    return map.map((key, config) => new MapEntry(
+        key,
+        config.change(
+            chosenPresets: config.chosenPresets.union(chosenPresets))));
   }
 
   /// Creates new Configuration.
@@ -589,7 +590,7 @@ class Configuration {
     var newPresets = new Map<String, Configuration>.from(presets);
     var merged = chosenPresets.fold(
         empty,
-        (merged, preset) =>
+        (Configuration merged, preset) =>
             merged.merge(newPresets.remove(preset) ?? Configuration.empty));
 
     if (merged == empty) return this;
diff --git a/lib/src/runner/configuration/args.dart b/lib/src/runner/configuration/args.dart
index cff98ee46c7c95f72a68dcab84a4b637d2569154..2f0fccfe1bc76df0fce3b50dfa1200cef1ec45dc 100644
--- a/lib/src/runner/configuration/args.dart
+++ b/lib/src/runner/configuration/args.dart
@@ -168,19 +168,21 @@ class _Parser {
         .toList()
           ..addAll(_options['plain-name'] as List<String>);
 
-    var includeTagSet = new Set.from(_options['tags'] ?? [])
-      ..addAll(_options['tag'] ?? []);
+    var includeTagSet = new Set.from(_options['tags'] as Iterable ?? [])
+      ..addAll(_options['tag'] as Iterable ?? []);
 
-    var includeTags = includeTagSet.fold(BooleanSelector.all, (selector, tag) {
-      var tagSelector = new BooleanSelector.parse(tag);
+    var includeTags = includeTagSet.fold(BooleanSelector.all,
+        (BooleanSelector selector, tag) {
+      var tagSelector = new BooleanSelector.parse(tag as String);
       return selector.intersection(tagSelector);
     });
 
-    var excludeTagSet = new Set.from(_options['exclude-tags'] ?? [])
-      ..addAll(_options['exclude-tag'] ?? []);
+    var excludeTagSet = new Set.from(_options['exclude-tags'] as Iterable ?? [])
+      ..addAll(_options['exclude-tag'] as Iterable ?? []);
 
-    var excludeTags = excludeTagSet.fold(BooleanSelector.none, (selector, tag) {
-      var tagSelector = new BooleanSelector.parse(tag);
+    var excludeTags = excludeTagSet.fold(BooleanSelector.none,
+        (BooleanSelector selector, tag) {
+      var tagSelector = new BooleanSelector.parse(tag as String);
       return selector.union(tagSelector);
     });
 
@@ -208,7 +210,7 @@ class _Parser {
         color: _ifParsed('color'),
         configurationPath: _ifParsed('configuration'),
         dart2jsPath: _ifParsed('dart2js-path'),
-        dart2jsArgs: _ifParsed('dart2js-args') as List<String>,
+        dart2jsArgs: _ifParsed('dart2js-args'),
         precompiledPath: _ifParsed('precompiled'),
         reporter: _ifParsed('reporter'),
         pubServePort: _parseOption('pub-serve', int.parse),
@@ -217,11 +219,11 @@ class _Parser {
         totalShards: totalShards,
         timeout: _parseOption('timeout', (value) => new Timeout.parse(value)),
         patterns: patterns,
-        runtimes: (_ifParsed('platform') as List<String>)
+        runtimes: _ifParsed<List<String>>('platform')
             ?.map((runtime) => new RuntimeSelection(runtime))
             ?.toList(),
         runSkipped: _ifParsed('run-skipped'),
-        chosenPresets: _ifParsed('preset') as List<String>,
+        chosenPresets: _ifParsed('preset'),
         paths: _options.rest.isEmpty ? null : _options.rest,
         includeTags: includeTags,
         excludeTags: excludeTags,
@@ -233,7 +235,8 @@ class _Parser {
   /// If the user hasn't explicitly chosen a value, we want to pass null values
   /// to [new Configuration] so that it considers those fields unset when
   /// merging with configuration from the config file.
-  _ifParsed(String name) => _options.wasParsed(name) ? _options[name] : null;
+  T _ifParsed<T>(String name) =>
+      _options.wasParsed(name) ? _options[name] as T : null;
 
   /// Runs [parse] on the value of the option [name], and wraps any
   /// [FormatException] it throws with additional information.
diff --git a/lib/src/runner/configuration/load.dart b/lib/src/runner/configuration/load.dart
index eba5df3177f156df83eaa8c57da9d6d06fc0780b..37c09f8d895f0c00f6479c0cf7e13536ead16bdc 100644
--- a/lib/src/runner/configuration/load.dart
+++ b/lib/src/runner/configuration/load.dart
@@ -5,7 +5,6 @@
 import 'dart:io';
 
 import 'package:boolean_selector/boolean_selector.dart';
-import 'package:collection/collection.dart';
 import 'package:glob/glob.dart';
 import 'package:path/path.dart' as p;
 import 'package:source_span/source_span.dart';
@@ -55,7 +54,8 @@ Configuration load(String path, {bool global = false}) {
         "The configuration must be a YAML map.", document.span, source);
   }
 
-  var loader = new _ConfigurationLoader(document, source, global: global);
+  var loader =
+      new _ConfigurationLoader(document as YamlMap, source, global: global);
   return loader.load();
 }
 
@@ -128,7 +128,7 @@ class _ConfigurationLoader {
           _validate(keyNode, "on_os key must be a string.",
               (value) => value is String);
 
-          var os = OperatingSystem.find(keyNode.value);
+          var os = OperatingSystem.find(keyNode.value as String);
           if (os != null) return os;
 
           throw new SourceSpanFormatException(
@@ -172,12 +172,15 @@ class _ConfigurationLoader {
       return Configuration.empty;
     }
 
-    var skip = _getValue("skip", "boolean or string",
+    var skipRaw = _getValue("skip", "boolean or string",
         (value) => value is bool || value is String);
-    var skipReason;
-    if (skip is String) {
-      skipReason = skip;
+    String skipReason;
+    bool skip;
+    if (skipRaw is String) {
+      skipReason = skipRaw;
       skip = true;
+    } else {
+      skip = skipRaw as bool;
     }
 
     var testOn = _parsePlatformSelector("test_on");
@@ -266,8 +269,8 @@ class _ConfigurationLoader {
 
     var runtimes = <String, RuntimeSettings>{};
     runtimesNode.nodes.forEach((identifierNode, valueNode) {
-      var identifier =
-          _parseIdentifierLike(identifierNode, "Platform identifier");
+      var identifier = _parseIdentifierLike(
+          identifierNode as YamlNode, "Platform identifier");
 
       _validate(valueNode, "Platform definition must be a map.",
           (value) => value is Map);
@@ -277,7 +280,7 @@ class _ConfigurationLoader {
       _validate(settings, "Must be a map.", (value) => value is Map);
 
       runtimes[identifier] = new RuntimeSettings(
-          identifier, identifierNode.span, [settings as YamlMap]);
+          identifier, (identifierNode as YamlNode).span, [settings as YamlMap]);
     });
     return runtimes;
   }
@@ -309,13 +312,13 @@ class _ConfigurationLoader {
       ..addAll(_getList("plain_names", (nameNode) {
         _validate(
             nameNode, "Names must be strings.", (value) => value is String);
-        return nameNode.value;
+        return _parseNode(nameNode, "name", (value) => new RegExp(value));
       }));
 
     var paths = _getList("paths", (pathNode) {
       _validate(pathNode, "Paths must be strings.", (value) => value is String);
       _validate(pathNode, "Paths must be relative.",
-          (value) => p.url.isRelative(value));
+          (value) => p.url.isRelative(value as String));
 
       return _parseNode(pathNode, "path", p.fromUri);
     });
@@ -356,7 +359,7 @@ class _ConfigurationLoader {
             _source);
       }
       foldOptionSet = true;
-      return keyNode.value;
+      return keyNode.value as String;
     }, value: (valueNode) {
       _validate(
           valueNode,
@@ -368,10 +371,10 @@ class _ConfigurationLoader {
       _validate(
           valueNode,
           "Invalid package name.",
-          (valueList) =>
-              valueList.every((value) => _packageName.hasMatch(value)));
+          (valueList) => (valueList as Iterable)
+              .every((value) => _packageName.hasMatch(value as String)));
 
-      return new List<String>.from(valueNode.value);
+      return new List<String>.from(valueNode.value as Iterable);
     });
   }
 
@@ -383,8 +386,8 @@ class _ConfigurationLoader {
 
     var runtimes = <String, CustomRuntime>{};
     runtimesNode.nodes.forEach((identifierNode, valueNode) {
-      var identifier =
-          _parseIdentifierLike(identifierNode, "Platform identifier");
+      var identifier = _parseIdentifierLike(
+          identifierNode as YamlNode, "Platform identifier");
 
       _validate(valueNode, "Platform definition must be a map.",
           (value) => value is Map);
@@ -400,8 +403,14 @@ class _ConfigurationLoader {
       var settings = _expect(map, "settings");
       _validate(settings, "Must be a map.", (value) => value is Map);
 
-      runtimes[identifier] = new CustomRuntime(name, nameNode.span, identifier,
-          identifierNode.span, parent, parentNode.span, settings as YamlMap);
+      runtimes[identifier] = new CustomRuntime(
+          name,
+          nameNode.span,
+          identifier,
+          (identifierNode as YamlNode).span,
+          parent,
+          parentNode.span,
+          settings as YamlMap);
     });
     return runtimes;
   }
@@ -435,19 +444,20 @@ class _ConfigurationLoader {
   }
 
   /// Asserts that [field] is an int and returns its value.
-  int _getInt(String field) => _getValue(field, "int", (value) => value is int);
+  int _getInt(String field) =>
+      _getValue(field, "int", (value) => value is int) as int;
 
   /// Asserts that [field] is a non-negative int and returns its value.
   int _getNonNegativeInt(String field) => _getValue(
-      field, "non-negative int", (value) => value is int && value >= 0);
+      field, "non-negative int", (value) => value is int && value >= 0) as int;
 
   /// Asserts that [field] is a boolean and returns its value.
   bool _getBool(String field) =>
-      _getValue(field, "boolean", (value) => value is bool);
+      _getValue(field, "boolean", (value) => value is bool) as bool;
 
   /// Asserts that [field] is a string and returns its value.
   String _getString(String field) =>
-      _getValue(field, "string", (value) => value is String);
+      _getValue(field, "string", (value) => value is String) as String;
 
   /// Asserts that [field] is a list and runs [forElement] for each element it
   /// contains.
@@ -482,9 +492,8 @@ class _ConfigurationLoader {
       return valueNode.value as V;
     };
 
-    return mapMap(node.nodes,
-        key: (keyNode, _) => key(keyNode),
-        value: (_, valueNode) => value(valueNode));
+    return node.nodes.map((keyNode, valueNode) =>
+        new MapEntry(key(keyNode as YamlNode), value(valueNode)));
   }
 
   /// Verifies that [node]'s value is an optionally hyphenated Dart identifier,
@@ -492,8 +501,8 @@ class _ConfigurationLoader {
   String _parseIdentifierLike(YamlNode node, String name) {
     _validate(node, "$name must be a string.", (value) => value is String);
     _validate(node, "$name must be an (optionally hyphenated) Dart identifier.",
-        (value) => value.contains(anchoredHyphenatedIdentifier));
-    return node.value;
+        (value) => (value as String).contains(anchoredHyphenatedIdentifier));
+    return node.value as String;
   }
 
   /// Parses [node]'s value as a boolean selector.
@@ -517,7 +526,7 @@ class _ConfigurationLoader {
     _validate(node, "$name must be a string.", (value) => value is String);
 
     try {
-      return parse(node.value);
+      return parse(node.value as String);
     } on FormatException catch (error) {
       throw new SourceSpanFormatException(
           'Invalid $name: ${error.message}', node.span, _source);
@@ -544,7 +553,7 @@ class _ConfigurationLoader {
     if (node == null || node.value == null) return Configuration.empty;
 
     _validate(node, "$name must be a map.", (value) => value is Map);
-    var loader = new _ConfigurationLoader(node, _source,
+    var loader = new _ConfigurationLoader(node as YamlMap, _source,
         global: _global, runnerConfig: runnerConfig ?? _runnerConfig);
     return loader.load();
   }
@@ -575,9 +584,7 @@ class _ConfigurationLoader {
       return base.isEmpty ? Configuration.empty : create(base);
     } else {
       var newPresets =
-          mapMap<String, Map<T, SuiteConfiguration>, String, Configuration>(
-              presets,
-              value: (_, map) => create(map));
+          presets.map((key, map) => new MapEntry(key, create(map)));
       return create(base).change(presets: newPresets);
     }
   }
@@ -598,7 +605,9 @@ class _ConfigurationLoader {
     throw new SourceSpanFormatException(
         "$field isn't supported here.",
         // We need the key as a [YamlNode] to get its span.
-        _document.nodes.keys.firstWhere((key) => key.value == field).span,
+        (_document.nodes.keys.firstWhere((key) => key.value == field)
+                as YamlNode)
+            .span,
         _source);
   }
 
diff --git a/lib/src/runner/configuration/suite.dart b/lib/src/runner/configuration/suite.dart
index 33a1db3fe33f92ad17fcaeeb6131d44185572361..75ed9c2ced19420a243cbf83581fa1956e70d90f 100644
--- a/lib/src/runner/configuration/suite.dart
+++ b/lib/src/runner/configuration/suite.dart
@@ -87,8 +87,9 @@ class SuiteConfiguration {
   Metadata get metadata {
     if (tags.isEmpty && onPlatform.isEmpty) return _metadata;
     return _metadata.change(
-        forTag: mapMap(tags, value: (_, config) => config.metadata),
-        onPlatform: mapMap(onPlatform, value: (_, config) => config.metadata));
+        forTag: tags.map((key, config) => new MapEntry(key, config.metadata)),
+        onPlatform: onPlatform
+            .map((key, config) => new MapEntry(key, config.metadata)));
   }
 
   final Metadata _metadata;
@@ -197,10 +198,10 @@ class SuiteConfiguration {
   /// [metadata].
   factory SuiteConfiguration.fromMetadata(Metadata metadata) =>
       new SuiteConfiguration._(
-          tags: mapMap(metadata.forTag,
-              value: (_, child) => new SuiteConfiguration.fromMetadata(child)),
-          onPlatform: mapMap(metadata.onPlatform,
-              value: (_, child) => new SuiteConfiguration.fromMetadata(child)),
+          tags: metadata.forTag.map((key, child) =>
+              new MapEntry(key, new SuiteConfiguration.fromMetadata(child))),
+          onPlatform: metadata.onPlatform.map((key, child) =>
+              new MapEntry(key, new SuiteConfiguration.fromMetadata(child))),
           metadata: metadata.change(forTag: {}, onPlatform: {}));
 
   /// Returns an unmodifiable copy of [input].
@@ -287,7 +288,7 @@ class SuiteConfiguration {
             retry: retry,
             skipReason: skipReason,
             testOn: testOn,
-            tags: addTags));
+            tags: addTags?.toSet()));
     return config._resolveTags();
   }
 
@@ -346,7 +347,7 @@ class SuiteConfiguration {
 
     // Otherwise, resolve the tag-specific components.
     var newTags = new Map<BooleanSelector, SuiteConfiguration>.from(tags);
-    var merged = tags.keys.fold(empty, (merged, selector) {
+    var merged = tags.keys.fold(empty, (SuiteConfiguration merged, selector) {
       if (!selector.evaluate(_metadata.tags)) return merged;
       return merged.merge(newTags.remove(selector));
     });
diff --git a/lib/src/runner/engine.dart b/lib/src/runner/engine.dart
index 77757eb348bee9da9cac7a9e1a5ae88fbf6b72b9..08f4d66f7526dad78440365ff8e9407de8586074 100644
--- a/lib/src/runner/engine.dart
+++ b/lib/src/runner/engine.dart
@@ -62,7 +62,7 @@ class Engine {
   /// This is `null` if close hasn't been called and the tests are still
   /// running, `true` if close was called before the tests finished running, and
   /// `false` if the tests finished running before close was called.
-  var _closedBeforeDone;
+  bool _closedBeforeDone;
 
   /// A pool that limits the number of test suites running concurrently.
   final Pool _runPool;
@@ -255,7 +255,7 @@ class Engine {
       _group.add(() async {
         var loadResource = await _loadPool.request();
 
-        var controller;
+        LiveSuiteController controller;
         if (suite is LoadSuite) {
           await _onUnpaused;
           controller = await _addLoadSuite(suite);
@@ -314,7 +314,7 @@ class Engine {
           if (entry is Group) {
             await _runGroup(suiteController, entry, parents);
           } else if (!suiteConfig.runSkipped && entry.metadata.skip) {
-            await _runSkippedTest(suiteController, entry, parents);
+            await _runSkippedTest(suiteController, entry as Test, parents);
           } else {
             var test = entry as Test;
             await _runLiveTest(suiteController,
@@ -390,7 +390,7 @@ class Engine {
     var skipped =
         new LocalTest(test.name, test.metadata, () {}, trace: test.trace);
 
-    var controller;
+    LiveTestController controller;
     controller =
         new LiveTestController(suiteController.liveSuite.suite, skipped, () {
       controller.setState(const State(Status.running, Result.success));
diff --git a/lib/src/runner/executable_settings.dart b/lib/src/runner/executable_settings.dart
index bce14943e46bb2e15aeb5184de6cce8b7014fe20..6199bc8d1199382fcb89eae4c7d6682d44dc6685 100644
--- a/lib/src/runner/executable_settings.dart
+++ b/lib/src/runner/executable_settings.dart
@@ -74,9 +74,10 @@ class ExecutableSettings {
     List<String> arguments;
     var argumentsNode = settings.nodes["arguments"];
     if (argumentsNode != null) {
-      if (argumentsNode.value is String) {
+      var value = argumentsNode.value;
+      if (value is String) {
         try {
-          arguments = shellSplit(argumentsNode.value);
+          arguments = shellSplit(value);
         } on FormatException catch (error) {
           throw new SourceSpanFormatException(
               error.message, argumentsNode.span);
@@ -92,14 +93,16 @@ class ExecutableSettings {
     String windowsExecutable;
     var executableNode = settings.nodes["executable"];
     if (executableNode != null) {
-      if (executableNode.value is String) {
+      var value = executableNode.value;
+      if (value is String) {
         // Don't check this on Windows because people may want to set relative
         // paths in their global config.
-        if (!Platform.isWindows) _assertNotRelative(executableNode);
+        if (!Platform.isWindows)
+          _assertNotRelative(executableNode as YamlScalar);
 
-        linuxExecutable = executableNode.value;
-        macOSExecutable = executableNode.value;
-        windowsExecutable = executableNode.value;
+        linuxExecutable = value;
+        macOSExecutable = value;
+        windowsExecutable = value;
       } else if (executableNode is YamlMap) {
         linuxExecutable = _getExecutable(executableNode.nodes["linux"]);
         macOSExecutable = _getExecutable(executableNode.nodes["mac_os"]);
@@ -114,8 +117,9 @@ class ExecutableSettings {
     var headless = true;
     var headlessNode = settings.nodes["headless"];
     if (headlessNode != null) {
-      if (headlessNode.value is bool) {
-        headless = headlessNode.value;
+      var value = headlessNode.value;
+      if (value is bool) {
+        headless = value;
       } else {
         throw new SourceSpanFormatException(
             "Must be a boolean.", headlessNode.span);
@@ -141,8 +145,8 @@ class ExecutableSettings {
       throw new SourceSpanFormatException(
           "Must be a string.", executableNode.span);
     }
-    if (!allowRelative) _assertNotRelative(executableNode);
-    return executableNode.value;
+    if (!allowRelative) _assertNotRelative(executableNode as YamlScalar);
+    return executableNode.value as String;
   }
 
   /// Throws a [SourceSpanFormatException] if [executableNode]'s value is a
diff --git a/lib/src/runner/load_exception.dart b/lib/src/runner/load_exception.dart
index 221a1bcb8d7af908c41ed951aa7f371209b59747..ffd5d6d0104c08a3ee2c1c10ffd923e27613a4f6 100644
--- a/lib/src/runner/load_exception.dart
+++ b/lib/src/runner/load_exception.dart
@@ -54,8 +54,9 @@ class LoadException implements Exception {
       innerString = innerString.split("Stack Trace:\n").first.trim();
     }
     if (innerError is SourceSpanException) {
-      innerString =
-          innerError.toString(color: color).replaceFirst(" of $path", "");
+      innerString = (innerError as SourceSpanException)
+          .toString(color: color)
+          .replaceFirst(" of $path", "");
     }
 
     buffer.write(innerString.contains("\n") ? "\n" : " ");
diff --git a/lib/src/runner/load_suite.dart b/lib/src/runner/load_suite.dart
index fc8b428d879072a4b4fc814684df1bea3d6e687b..68a465e680c58da92c3710d516963c0e789b5052 100644
--- a/lib/src/runner/load_suite.dart
+++ b/lib/src/runner/load_suite.dart
@@ -167,7 +167,7 @@ class LoadSuite extends Suite implements RunnerSuite {
       if (pair == null) return null;
 
       var zone = pair.last;
-      var newSuite;
+      RunnerSuite newSuite;
       zone.runGuarded(() {
         newSuite = change(pair.first);
       });
diff --git a/lib/src/runner/parse_metadata.dart b/lib/src/runner/parse_metadata.dart
index e8aa1ae22417770e204531464816423cf91252b6..3ef78aaac28d5280a9ccfdd46f41d6f8c530f9a8 100644
--- a/lib/src/runner/parse_metadata.dart
+++ b/lib/src/runner/parse_metadata.dart
@@ -6,7 +6,6 @@ import 'dart:io';
 
 import 'package:analyzer/analyzer.dart';
 import 'package:analyzer/dart/ast/ast.dart';
-import 'package:collection/collection.dart';
 import 'package:path/path.dart' as p;
 import 'package:source_span/source_span.dart';
 
@@ -236,7 +235,7 @@ class _Parser {
     return _parseMap(annotation.arguments.arguments.first, key: (key) {
       return _parsePlatformSelector(key);
     }, value: (value) {
-      var expressions = [];
+      var expressions = <AstNode>[];
       if (value is ListLiteral) {
         expressions = _parseList(value);
       } else if (value is InstanceCreationExpression ||
@@ -247,8 +246,8 @@ class _Parser {
             'Expected a Timeout, Skip, or List of those.', _spanFor(value));
       }
 
-      var timeout;
-      var skip;
+      Timeout timeout;
+      dynamic skip;
       for (var expression in expressions) {
         if (expression is InstanceCreationExpression) {
           var className = _resolveConstructor(
@@ -300,8 +299,8 @@ class _Parser {
       'microseconds'
     ]);
 
-    var values =
-        mapMap(valueExpressions, value: (_, value) => _parseInt(value));
+    var values = valueExpressions
+        .map((key, value) => new MapEntry(key, _parseInt(value)));
 
     return new Duration(
         days: values["days"] == null ? 0 : values["days"],
@@ -516,8 +515,8 @@ class _Parser {
           "Map literals must be const.", _spanFor(map));
     }
 
-    return new Map.fromIterable(map.entries,
-        key: (entry) => key(entry.key), value: (entry) => value(entry.value));
+    return new Map.fromIterables(map.entries.map((e) => key(e.key)),
+        map.entries.map((e) => value(e.value)));
   }
 
   /// Parses a List literal.
@@ -569,7 +568,7 @@ class _Parser {
 
   /// Runs [fn] and contextualizes any [SourceSpanFormatException]s that occur
   /// in it relative to [literal].
-  _contextualize(StringLiteral literal, fn()) {
+  T _contextualize<T>(StringLiteral literal, T fn()) {
     try {
       return fn();
     } on SourceSpanFormatException catch (error) {
diff --git a/lib/src/runner/plugin/platform_helpers.dart b/lib/src/runner/plugin/platform_helpers.dart
index a219058a9940d238e337ac0cce05c82d57735156..1d6a2607d3442d8d15152e4ccb24d4558bca3626 100644
--- a/lib/src/runner/plugin/platform_helpers.dart
+++ b/lib/src/runner/plugin/platform_helpers.dart
@@ -54,12 +54,12 @@ RunnerSuiteController deserializeSuite(
     'noRetry': Configuration.current.noRetry,
     'foldTraceExcept': Configuration.current.foldTraceExcept.toList(),
     'foldTraceOnly': Configuration.current.foldTraceOnly.toList(),
-  }..addAll(message as Map));
+  }..addAll(message as Map<String, dynamic>));
 
   var completer = new Completer<Group>();
 
   var loadSuiteZone = Zone.current;
-  handleError(error, stackTrace) {
+  handleError(error, StackTrace stackTrace) {
     disconnector.disconnect();
 
     if (completer.isCompleted) {
@@ -74,7 +74,7 @@ RunnerSuiteController deserializeSuite(
 
   suiteChannel.stream.listen(
       (response) {
-        switch (response["type"]) {
+        switch (response["type"] as String) {
           case "print":
             print(response["line"]);
             break;
@@ -92,7 +92,8 @@ RunnerSuiteController deserializeSuite(
 
           case "success":
             var deserializer = new _Deserializer(suiteChannel);
-            completer.complete(deserializer.deserializeGroup(response["root"]));
+            completer.complete(
+                deserializer.deserializeGroup(response["root"] as Map));
             break;
         }
       },
@@ -122,16 +123,18 @@ class _Deserializer {
   Group deserializeGroup(Map group) {
     var metadata = new Metadata.deserialize(group['metadata']);
     return new Group(
-        group['name'],
+        group['name'] as String,
         (group['entries'] as List).map((entry) {
           var map = entry as Map;
           if (map['type'] == 'group') return deserializeGroup(map);
           return _deserializeTest(map);
         }),
         metadata: metadata,
-        trace: group['trace'] == null ? null : new Trace.parse(group['trace']),
-        setUpAll: _deserializeTest(group['setUpAll']),
-        tearDownAll: _deserializeTest(group['tearDownAll']));
+        trace: group['trace'] == null
+            ? null
+            : new Trace.parse(group['trace'] as String),
+        setUpAll: _deserializeTest(group['setUpAll'] as Map),
+        tearDownAll: _deserializeTest(group['tearDownAll'] as Map));
   }
 
   /// Deserializes [test] into a concrete [Test] class.
@@ -141,8 +144,9 @@ class _Deserializer {
     if (test == null) return null;
 
     var metadata = new Metadata.deserialize(test['metadata']);
-    var trace = test['trace'] == null ? null : new Trace.parse(test['trace']);
+    var trace =
+        test['trace'] == null ? null : new Trace.parse(test['trace'] as String);
     var testChannel = _channel.virtualChannel(test['channel']);
-    return new RunnerTest(test['name'], metadata, trace, testChannel);
+    return new RunnerTest(test['name'] as String, metadata, trace, testChannel);
   }
 }
diff --git a/lib/src/runner/remote_listener.dart b/lib/src/runner/remote_listener.dart
index c8b2c9108e34892b3821d43eec8f56fa392b0b51..0e12c60dbb69aa5dd8f316e428e8fe2afd220b5a 100644
--- a/lib/src/runner/remote_listener.dart
+++ b/lib/src/runner/remote_listener.dart
@@ -67,7 +67,7 @@ class RemoteListener {
     new SuiteChannelManager().asCurrent(() {
       new StackTraceFormatter().asCurrent(() {
         runZoned(() async {
-          var main;
+          dynamic main;
           try {
             main = getMain();
           } on NoSuchMethodError catch (_) {
@@ -95,30 +95,31 @@ class RemoteListener {
 
           queue.rest.listen((message) {
             assert(message["type"] == "suiteChannel");
-            SuiteChannelManager.current.connectIn(
-                message['name'], channel.virtualChannel(message['id']));
+            SuiteChannelManager.current.connectIn(message['name'] as String,
+                channel.virtualChannel(message['id']));
           });
 
-          if (message['asciiGlyphs'] ?? false) glyph.ascii = true;
+          if ((message['asciiGlyphs'] as bool) ?? false) glyph.ascii = true;
           var metadata = new Metadata.deserialize(message['metadata']);
           verboseChain = metadata.verboseTrace;
           var declarer = new Declarer(
               metadata: metadata,
-              platformVariables: new Set.from(message['platformVariables']),
-              collectTraces: message['collectTraces'],
-              noRetry: message['noRetry']);
+              platformVariables:
+                  new Set.from(message['platformVariables'] as Iterable),
+              collectTraces: message['collectTraces'] as bool,
+              noRetry: message['noRetry'] as bool);
 
           StackTraceFormatter.current.configure(
-              except: _deserializeSet(message['foldTraceExcept']),
-              only: _deserializeSet(message['foldTraceOnly']));
+              except: _deserializeSet(message['foldTraceExcept'] as List),
+              only: _deserializeSet(message['foldTraceOnly'] as List));
 
           if (beforeLoad != null) await beforeLoad();
 
-          await declarer.declare(main);
+          await declarer.declare(main as Function());
 
           var suite = new Suite(declarer.build(),
               new SuitePlatform.deserialize(message['platform']),
-              path: message['path']);
+              path: message['path'] as String);
 
           runZoned(() {
             Invoker.guard(
@@ -128,7 +129,7 @@ class RemoteListener {
               // useful errors when calling `test()` and `group()` within a test,
               // and so they can add to the declarer's `tearDownAll()` list.
               zoneValues: {#test.declarer: declarer});
-        }, onError: (error, stackTrace) {
+        }, onError: (error, StackTrace stackTrace) {
           _sendError(channel, error, stackTrace, verboseChain);
         }, zoneSpecification: spec);
       });
@@ -190,7 +191,7 @@ class RemoteListener {
       "entries": group.entries.map((entry) {
         return entry is Group
             ? _serializeGroup(channel, entry, parents)
-            : _serializeTest(channel, entry, parents);
+            : _serializeTest(channel, entry as Test, parents);
       }).toList()
     };
   }
diff --git a/lib/src/runner/reporter/compact.dart b/lib/src/runner/reporter/compact.dart
index 5635445ce640af23960e421a2998f12492650010..89cfa11c8aee4d24fa6ed2109f60b34b5c4b7c09 100644
--- a/lib/src/runner/reporter/compact.dart
+++ b/lib/src/runner/reporter/compact.dart
@@ -212,7 +212,8 @@ class CompactReporter implements Reporter {
       return;
     }
 
-    print(indent(error.toString(color: _config.color)));
+    // TODO - what type is this?
+    print(indent(error.toString(color: _config.color) as String));
 
     // Only print stack traces for load errors that come from the user's code.
     if (error.innerError is! IOException &&
diff --git a/lib/src/runner/reporter/expanded.dart b/lib/src/runner/reporter/expanded.dart
index d5b7ac924c89a8d1f5bc28e6136d85e7089e6a83..673e78f7e93548b09a78b176b26dc7d3839ba94e 100644
--- a/lib/src/runner/reporter/expanded.dart
+++ b/lib/src/runner/reporter/expanded.dart
@@ -200,7 +200,8 @@ class ExpandedReporter implements Reporter {
       return;
     }
 
-    print(indent(error.toString(color: _color)));
+    // TODO - what type is this?
+    print(indent((error as dynamic).toString(color: _color) as String));
 
     // Only print stack traces for load errors that come from the user's code.
     if (error.innerError is! IsolateSpawnException &&
diff --git a/lib/src/runner/runner_test.dart b/lib/src/runner/runner_test.dart
index 0dad8b781768fd1994edb85af34f05a65fd418c6..ff34d9715010478eb15ec5e8952894f662f6a40f 100644
--- a/lib/src/runner/runner_test.dart
+++ b/lib/src/runner/runner_test.dart
@@ -32,8 +32,8 @@ class RunnerTest extends Test {
   RunnerTest._(this.name, this.metadata, this.trace, this._channel);
 
   LiveTest load(Suite suite, {Iterable<Group> groups}) {
-    var controller;
-    var testChannel;
+    LiveTestController controller;
+    VirtualChannel testChannel;
     controller = new LiveTestController(suite, this, () {
       controller.setState(const State(Status.running, Result.success));
 
@@ -41,7 +41,7 @@ class RunnerTest extends Test {
       _channel.sink.add({'command': 'run', 'channel': testChannel.id});
 
       testChannel.stream.listen((message) {
-        switch (message['type']) {
+        switch (message['type'] as String) {
           case 'error':
             var asyncError = RemoteException.deserialize(message['error']);
             var stackTrace = asyncError.stackTrace;
@@ -49,14 +49,15 @@ class RunnerTest extends Test {
             break;
 
           case 'state-change':
-            controller.setState(new State(new Status.parse(message['status']),
-                new Result.parse(message['result'])));
+            controller.setState(new State(
+                new Status.parse(message['status'] as String),
+                new Result.parse(message['result'] as String)));
             break;
 
           case 'message':
             controller.message(new Message(
-                new MessageType.parse(message['message-type']),
-                message['text']));
+                new MessageType.parse(message['message-type'] as String),
+                message['text'] as String));
             break;
 
           case 'complete':
@@ -67,7 +68,7 @@ class RunnerTest extends Test {
             // When we kill the isolate that the test lives in, that will close
             // this virtual channel and cause the spawned isolate to close as
             // well.
-            spawnHybridUri(message['url'], message['message'])
+            spawnHybridUri(message['url'] as String, message['message'])
                 .pipe(testChannel.virtualChannel(message['channel']));
             break;
         }
diff --git a/lib/src/runner/version.dart b/lib/src/runner/version.dart
index 363a9a15df2280fcbf2b429581ce5010875ed356..b3d9be5c5f0206c8198f05a4f4763bf4d9d98381 100644
--- a/lib/src/runner/version.dart
+++ b/lib/src/runner/version.dart
@@ -29,7 +29,7 @@ final String testVersion = (() {
   var source = package["source"];
   if (source is! String) return null;
 
-  switch (source) {
+  switch (source as String) {
     case "hosted":
       var version = package["version"];
       if (version is! String) return null;
diff --git a/lib/src/runner/vm/catch_isolate_errors.dart b/lib/src/runner/vm/catch_isolate_errors.dart
index e27a065df5a265f043534116471b38339e0a55de..796c35aca5bff0d47dd2b00b80887dfc2eead40b 100644
--- a/lib/src/runner/vm/catch_isolate_errors.dart
+++ b/lib/src/runner/vm/catch_isolate_errors.dart
@@ -17,9 +17,10 @@ void catchIsolateErrors() {
   errorPort.listen((message) {
     // Masquerade as an IsolateSpawnException because that's what this would
     // be if the error had been detected statically.
-    var error = new IsolateSpawnException(message[0]);
-    var stackTrace =
-        message[1] == null ? new Trace([]) : new Trace.parse(message[1]);
+    var error = new IsolateSpawnException(message[0] as String);
+    var stackTrace = message[1] == null
+        ? new Trace([])
+        : new Trace.parse(message[1] as String);
     Zone.current.handleUncaughtError(error, stackTrace);
   });
 }
diff --git a/lib/src/util/io.dart b/lib/src/util/io.dart
index 46d6a3cee3a2065e12866926df7395ac50fb592f..3df47929bf89535ef298605e6d2cfab9858c5cbb 100644
--- a/lib/src/util/io.dart
+++ b/lib/src/util/io.dart
@@ -175,20 +175,22 @@ var _maySupportIPv6 = true;
 /// any time after this call has returned. If at all possible, callers should
 /// use [getUnusedPort] instead.
 Future<int> getUnsafeUnusedPort() async {
-  var socket;
+  int port;
   if (_maySupportIPv6) {
     try {
-      socket = await ServerSocket.bind(InternetAddress.loopbackIPv6, 0,
+      final socket = await ServerSocket.bind(InternetAddress.loopbackIPv6, 0,
           v6Only: true);
+      port = socket.port;
+      await socket.close();
     } on SocketException {
       _maySupportIPv6 = false;
     }
   }
   if (!_maySupportIPv6) {
-    socket = await RawServerSocket.bind(InternetAddress.loopbackIPv4, 0);
+    final socket = await RawServerSocket.bind(InternetAddress.loopbackIPv4, 0);
+    port = socket.port;
+    await socket.close();
   }
-  var port = socket.port;
-  await socket.close();
   return port;
 }
 
@@ -204,7 +206,7 @@ Future<Uri> getRemoteDebuggerUrl(Uri base) async {
     var response = await request.close();
     var jsonObject =
         await json.fuse(utf8).decoder.bind(response).single as List;
-    return base.resolve(jsonObject.first["devtoolsFrontendUrl"]);
+    return base.resolve(jsonObject.first["devtoolsFrontendUrl"] as String);
   } catch (_) {
     // If we fail to talk to the remote debugger protocol, give up and return
     // the raw URL rather than crashing.
diff --git a/lib/src/util/remote_exception.dart b/lib/src/util/remote_exception.dart
index f68ff2175ca435d2037f14bdb98be8aefa41de52..1ad0f5f8499fec36a92ab55aff359a98e1c0c2cc 100644
--- a/lib/src/util/remote_exception.dart
+++ b/lib/src/util/remote_exception.dart
@@ -67,16 +67,16 @@ class RemoteException implements Exception {
   /// error and a [Chain] as its stack trace.
   static AsyncError deserialize(serialized) {
     return new AsyncError(_deserializeException(serialized),
-        new Chain.parse(serialized['stackChain']));
+        new Chain.parse(serialized['stackChain'] as String));
   }
 
   /// Deserializes the exception portion of [serialized].
   static RemoteException _deserializeException(serialized) {
-    var message = serialized['message'];
-    var type = serialized['type'];
-    var toString = serialized['toString'];
+    String message = serialized['message'];
+    String type = serialized['type'];
+    String toString = serialized['toString'];
 
-    switch (serialized['supertype']) {
+    switch (serialized['supertype'] as String) {
       case 'TestFailure':
         return new _RemoteTestFailure(message, type, toString);
       case 'IsolateSpawnException':
diff --git a/lib/src/util/stack_trace_mapper.dart b/lib/src/util/stack_trace_mapper.dart
index 4c02a3159e62a31cd1203afb27263607999e1c13..75a35759ac45f031225800f034b167ba2482776c 100644
--- a/lib/src/util/stack_trace_mapper.dart
+++ b/lib/src/util/stack_trace_mapper.dart
@@ -2,7 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:collection/collection.dart';
 import 'package:package_resolver/package_resolver.dart';
 import 'package:source_map_stack_trace/source_map_stack_trace.dart' as mapper;
 import 'package:source_maps/source_maps.dart';
@@ -56,13 +55,15 @@ class StackTraceMapper {
   static StackTraceMapper deserialize(Map serialized) {
     if (serialized == null) return null;
     String packageRoot = serialized['packageRoot'] as String ?? '';
-    return new StackTraceMapper(serialized['mapContents'],
-        sdkRoot: Uri.parse(serialized['sdkRoot']),
+    return new StackTraceMapper(serialized['mapContents'] as String,
+        sdkRoot: Uri.parse(serialized['sdkRoot'] as String),
         packageResolver: packageRoot.isNotEmpty
-            ? new SyncPackageResolver.root(Uri.parse(serialized['packageRoot']))
+            ? new SyncPackageResolver.root(
+                Uri.parse(serialized['packageRoot'] as String))
             : new SyncPackageResolver.config(_deserializePackageConfigMap(
-                serialized['packageConfigMap'].cast<String, String>())),
-        mapUrl: Uri.parse(serialized['mapUrl']));
+                (serialized['packageConfigMap'] as Map)
+                    .cast<String, String>())),
+        mapUrl: Uri.parse(serialized['mapUrl'] as String));
   }
 
   /// Converts a [packageConfigMap] into a format suitable for JSON
@@ -70,7 +71,7 @@ class StackTraceMapper {
   static Map<String, String> _serializePackageConfigMap(
       Map<String, Uri> packageConfigMap) {
     if (packageConfigMap == null) return null;
-    return mapMap(packageConfigMap, value: (_, value) => '$value');
+    return packageConfigMap.map((key, value) => new MapEntry(key, '$value'));
   }
 
   /// Converts a serialized package config map into a format suitable for
@@ -78,6 +79,6 @@ class StackTraceMapper {
   static Map<String, Uri> _deserializePackageConfigMap(
       Map<String, String> serialized) {
     if (serialized == null) return null;
-    return mapMap(serialized, value: (_, value) => Uri.parse(value));
+    return serialized.map((key, value) => new MapEntry(key, Uri.parse(value)));
   }
 }
diff --git a/lib/src/util/string_literal_iterator.dart b/lib/src/util/string_literal_iterator.dart
index eb7b3f0114630ffb68cfa76060c686d58af16000..2f26ba34de8a4fa9296dc2517e7b22232b0a0b67 100644
--- a/lib/src/util/string_literal_iterator.dart
+++ b/lib/src/util/string_literal_iterator.dart
@@ -89,8 +89,7 @@ class StringLiteralIterator extends Iterator<int> {
         if (string is StringInterpolation) {
           throw new ArgumentError("Can't iterate over an interpolated string.");
         }
-        assert(string is SimpleStringLiteral);
-        _strings.add(string);
+        _strings.add(string as SimpleStringLiteral);
       }
     }
 
diff --git a/test/frontend/matcher/prints_test.dart b/test/frontend/matcher/prints_test.dart
index 3445a099e4827c0f8da48e4bb068d292edd16424..d0cdbfbcb1fd0b9e83ae65e25cd349159f9e34a1 100644
--- a/test/frontend/matcher/prints_test.dart
+++ b/test/frontend/matcher/prints_test.dart
@@ -90,7 +90,7 @@ void main() {
           liveTest,
           "Expected: prints contains 'Goodbye'\n"
           "  Actual: <10>\n"
-          "   Which: was not a Function\n");
+          "   Which: was not a unary Function\n");
     });
   });