Updated charted DEP to 0.4.X

R=johnmccutchan@google.com

Review URL: https://codereview.chromium.org//2213693002 .
diff --git a/packages/charted/.analysis_options b/packages/charted/.analysis_options
new file mode 100644
index 0000000..5a05cd1
--- /dev/null
+++ b/packages/charted/.analysis_options
@@ -0,0 +1,4 @@
+analyzer:
+  strong-mode: true
+  exclude:
+    - test.disabled/**
\ No newline at end of file
diff --git a/packages/charted/examples/charts/components/demo_custom_axis.dart b/packages/charted/examples/charts/components/demo_custom_axis.dart
index 0d1f6a7..739bf6d 100644
--- a/packages/charted/examples/charts/components/demo_custom_axis.dart
+++ b/packages/charted/examples/charts/components/demo_custom_axis.dart
@@ -12,7 +12,7 @@
 import 'package:charted/charts/charts.dart';
 import 'package:charted/core/scales.dart';
 
-List COLUMNS = [
+List<ChartColumnSpec> COLUMNS = <ChartColumnSpec>[
     new ChartColumnSpec(label:'Month', type:ChartColumnSpec.TYPE_STRING),
     new ChartColumnSpec(label:'Precipitation'),
     new ChartColumnSpec(label:'High Temperature'),
@@ -23,7 +23,7 @@
     new ChartColumnSpec(label:'Extra3'),
   ];
 
-List DATA = [
+List<List> DATA = <List>[
     ['January',  4.50, 27, 46, 1,   20, 23, 1],
     ['February', 4.61, 60, 28, 10,  15, 45, 23],
     ['March',    3.26, 32, 49, 100, 4,  34, 1],
diff --git a/packages/charted/examples/charts/demo_charts.dart b/packages/charted/examples/charts/demo_charts.dart
index 45b4eb9..9de7b05 100644
--- a/packages/charted/examples/charts/demo_charts.dart
+++ b/packages/charted/examples/charts/demo_charts.dart
@@ -3,18 +3,18 @@
 import "package:charted/charts/charts.dart";
 
 /// Helper method to create default behaviors for cartesian chart demos.
-Iterable<ChartBehavior> createDefaultCartesianBehaviors() =>
+List<ChartBehavior> createDefaultCartesianBehaviors() =>
     new List.from([
         new Hovercard(isMultiValue: true),
         new AxisLabelTooltip()
     ]);
 
 /// Helper method to create default behaviors for layout chart demos.
-Iterable<ChartBehavior> createDefaultLayoutBehaviors() =>
+List<ChartBehavior> createDefaultLayoutBehaviors() =>
     new List.from([new ChartTooltip()]);
 
 /// Sample columns used by demos with quantitative dimension scale
-Iterable ORDINAL_DATA_COLUMNS = [
+List<ChartColumnSpec> ORDINAL_DATA_COLUMNS = <ChartColumnSpec>[
     new ChartColumnSpec(label: 'Month', type: ChartColumnSpec.TYPE_STRING),
     new ChartColumnSpec(label: 'Grains'),
     new ChartColumnSpec(label: 'Fruits'),
@@ -22,7 +22,7 @@
 ];
 
 /// Sample values used by demos with quantitative dimension scale
-Iterable ORDINAL_DATA = const [
+List<List> ORDINAL_DATA = const <List>[
     const ['January',   4.50,  7,  6],
     const ['February',  5.61, 16,  8],
     const ['March',     8.26, 36,  9],
@@ -38,7 +38,7 @@
 ];
 
 /// Sample values used by RTL demos with quantitative dimension scale
-Iterable ORDINAL_DATA_RTL = const [
+List<List> ORDINAL_DATA_RTL = const <List>[
     const ['كانون الثاني',   4.50,  7,  6],
     const ['شباط',  5.61, 16,  8],
     const ['آذار',     8.26, 36,  9],
@@ -53,7 +53,7 @@
     const ['كانون الأول',  8.46, 19,  3]
 ];
 
-Iterable ORDINAL_DATA_WITH_NEGATIVE = const [
+List<List> ORDINAL_DATA_WITH_NEGATIVE = const <List>[
     const ['January',   4.50,  -7,   6],
     const ['February',  5.61, -16,   8],
     const ['March',     8.26,  36,   9],
@@ -68,7 +68,7 @@
     const ['December',  8.46,  19,   3]
 ];
 
-Iterable ORDINAL_DATA_WITH_BREAKS = const [
+List<List> ORDINAL_DATA_WITH_BREAKS = const <List>[
     const ['January',   4.50,  -7,   6],
     const ['February',  5.61, -16,   8],
     const ['March',     8.26,  36,   9],
@@ -84,14 +84,14 @@
 ];
 
 /// Sample columns used by demos with quantitative dimension scale
-Iterable TIMESERIES_DATA_COLUMNS = [
+List<ChartColumnSpec> TIMESERIES_DATA_COLUMNS = <ChartColumnSpec>[
     new ChartColumnSpec(label: 'Time', type: ChartColumnSpec.TYPE_TIMESTAMP),
     new ChartColumnSpec(label: 'New York'),
     new ChartColumnSpec(label: 'San Fransisco'),
     new ChartColumnSpec(label: 'Austin')
 ];
 
-Iterable TIMESERIES_DATA = const [
+List<List<num>> TIMESERIES_DATA = const <List<num>>[
     const [1317452400000, 63.4, 62.7, 72.2],
     const [1317538800000, 58.0, 59.9, 67.7],
     const [1317625200000, 53.3, 59.1, 69.4],
diff --git a/packages/charted/examples/charts/demo_interactive.dart b/packages/charted/examples/charts/demo_interactive.dart
index 4688866..f577b5f 100644
--- a/packages/charted/examples/charts/demo_interactive.dart
+++ b/packages/charted/examples/charts/demo_interactive.dart
@@ -14,7 +14,7 @@
 
 import 'demo_charts.dart';
 
-const List DIMENSION_COLUMNS =  const[0, 4];
+const List<int> DIMENSION_COLUMNS =  const <int>[0, 4];
 
 int customSeriesCounter = 0;
 
@@ -40,14 +40,14 @@
 }
 
 main() {
-  List DATA_SOURCE = ORDINAL_DATA;
+  List<List> DATA_SOURCE = ORDINAL_DATA;
   ChartSeries activeSeries,
       defaultSeries = new ChartSeries("Default series",
           new ObservableList.from([ 2, 3 ]), new BarChartRenderer());
 
-  ObservableList rows = new ObservableList.from(DATA_SOURCE.sublist(0, 10)),
-      columns = new ObservableList.from(ORDINAL_DATA_COLUMNS),
-      seriesList = new ObservableList.from([ defaultSeries ]);
+  var rows = new ObservableList<List>.from(DATA_SOURCE.sublist(0, 10));
+  var columns = new ObservableList<ChartColumnSpec>.from(ORDINAL_DATA_COLUMNS);
+  var seriesList = new ObservableList<ChartSeries>.from([ defaultSeries ]);
 
   ChartData data = new ChartData(columns, rows);
   ChartConfig config = new ChartConfig(seriesList, DIMENSION_COLUMNS);
@@ -71,7 +71,6 @@
       removeSeriesButton = querySelector('#remove-series');
 
   InputElement useRTLScriptCheckBox = querySelector('#rtl-use-script'),
-      switchAxesForRTLCheckBox = querySelector('#rtl-switch-axes'),
       useRTLLayoutCheckBox = querySelector('#rtl-use-layout');
 
   SelectElement seriesSelect = querySelector('#select-series'),
@@ -192,7 +191,9 @@
     int index = buttons.indexOf(e.target) + 1;
     if ((e.target as InputElement).checked) {
       measures.add(index);
-      buttons.forEach((InputElement b) => b.disabled = false);
+      buttons.forEach((Element b) {
+        (b as InputElement).disabled = false;
+      });
     } else {
       measures.remove(index);
       if (measures.length <= 1) firstChecked.disabled = true;
diff --git a/packages/charted/examples/charts/renderers/demo_cartesian_renderers.dart b/packages/charted/examples/charts/renderers/demo_cartesian_renderers.dart
index e027d5b..c7b4de9 100644
--- a/packages/charted/examples/charts/renderers/demo_cartesian_renderers.dart
+++ b/packages/charted/examples/charts/renderers/demo_cartesian_renderers.dart
@@ -188,7 +188,6 @@
 
   Element chartsContainer = querySelector('.demos-container');
   InputElement useRTLScriptCheckBox = querySelector('#rtl-use-script'),
-      switchAxesForRTLCheckBox = querySelector('#rtl-switch-axes'),
       useRTLLayoutCheckBox = querySelector('#rtl-use-layout');
 
   useRTLLayoutCheckBox.onChange.listen((_) {
@@ -199,7 +198,7 @@
 
   useRTLScriptCheckBox.onChange.listen((_) {
     bool isRTL = useRTLScriptCheckBox.checked;
-    Iterable DATA_SOURCE = isRTL
+    List<List> DATA_SOURCE = isRTL
         ? ORDINAL_DATA_RTL
         : ORDINAL_DATA;
     charts.forEach((ChartDemo x) {
diff --git a/packages/charted/lib/charts/behaviors/axis_label_tooltip.dart b/packages/charted/lib/charts/behaviors/axis_label_tooltip.dart
index 092db6b..43c950b 100644
--- a/packages/charted/lib/charts/behaviors/axis_label_tooltip.dart
+++ b/packages/charted/lib/charts/behaviors/axis_label_tooltip.dart
@@ -38,8 +38,8 @@
   void _subscribe() {
     var elements = _area.host.querySelectorAll(_AXIS_SELECTOR);
     _disposer.dispose();
-    _disposer
-        .addAll(elements.map((x) => x.onMouseOver.listen(_handleMouseOver)));
+    _disposer.addAll(
+        elements.map((Element x) => x.onMouseOver.listen(_handleMouseOver)));
     _disposer.addAll(elements.map((x) => x.onMouseOut.listen(_handleMouseOut)));
   }
 
@@ -88,7 +88,7 @@
   void ensureRenderAreaRect() {
     var layout = _area.layout;
     _hostAreaRect = _area.host.getBoundingClientRect();
-    _renderAreaRect = new math.Rectangle(
+    _renderAreaRect = new math.Rectangle<num>(
         _hostAreaRect.left + layout.chartArea.x + layout.renderArea.x,
         _hostAreaRect.top + layout.chartArea.y + layout.renderArea.y,
         layout.renderArea.width,
diff --git a/packages/charted/lib/charts/behaviors/chart_tooltip.dart b/packages/charted/lib/charts/behaviors/chart_tooltip.dart
index 083d0f8..85d4b55 100644
--- a/packages/charted/lib/charts/behaviors/chart_tooltip.dart
+++ b/packages/charted/lib/charts/behaviors/chart_tooltip.dart
@@ -91,9 +91,18 @@
     // tooltip for them, if none is selected/hovered, show all.
     var activeMeasures = [];
     if (showSelectedMeasure) {
-      activeMeasures.addAll(_state.selection);
-      activeMeasures
-          .add(_state.preview != null ? _state.preview : _state.hovered.first);
+      if(_state != null) {
+        activeMeasures.addAll(_state.selection);
+        activeMeasures
+            .add(_state.preview != null
+                ? _state.preview
+                : _state.hovered.first);
+      } else {
+
+        // If state is null, chart tooltip will not capture selection, but only
+        // display for the currently hovered measure column.
+        activeMeasures.add(e.column);
+      }
       if (activeMeasures.isEmpty) {
         for (var series in _area.config.series) {
           activeMeasures.addAll(series.measures);
diff --git a/packages/charted/lib/charts/behaviors/hovercard.dart b/packages/charted/lib/charts/behaviors/hovercard.dart
index ff62aa7..3654ea8 100644
--- a/packages/charted/lib/charts/behaviors/hovercard.dart
+++ b/packages/charted/lib/charts/behaviors/hovercard.dart
@@ -78,7 +78,7 @@
       {bool isMouseTracking,
       bool isMultiValue: false,
       bool showDimensionTitle: false,
-      List columnsToShow: const [],
+      List<int> columnsToShow: const <int>[],
       this.builder}) {
     _isMouseTracking = isMouseTracking;
     _isMultiValue = isMultiValue;
@@ -205,7 +205,7 @@
     // update position and offset accordingly.
     if (area.dimensionsUsingBands.contains(dimensionCol)) {
       assert(dimensionScale is OrdinalScale);
-      dimensionOffset = (dimensionScale as OrdinalScale).rangeBand / 2;
+      dimensionOffset = (dimensionScale as OrdinalScale).rangeBand ~/ 2;
       dimensionCenterOffset = dimensionOffset;
     }
 
diff --git a/packages/charted/lib/charts/cartesian_renderers/bar_chart_renderer.dart b/packages/charted/lib/charts/cartesian_renderers/bar_chart_renderer.dart
index 74e93ca..37f6dcf 100644
--- a/packages/charted/lib/charts/cartesian_renderers/bar_chart_renderer.dart
+++ b/packages/charted/lib/charts/cartesian_renderers/bar_chart_renderer.dart
@@ -47,7 +47,7 @@
 
     var bars = new OrdinalScale()
       ..domain = new Range(series.measures.length).toList()
-      ..rangeRoundBands([0, dimensionScale.rangeBand]);
+      ..rangeRoundBands([0, (dimensionScale as OrdinalScale).rangeBand]);
 
     // Create and update the bar groups.
 
@@ -95,15 +95,31 @@
               ? (d >= 0 ? scaled0 - scaledVal : scaledVal - scaled0)
               : (d >= 0 ? scaledVal - scaled0 : scaled0 - scaledVal);
       ht = ht - strokeWidth;
-      return (ht < 0) ? 0 : ht;
+
+      // If bar would be scaled to 0 height but data is not 0, render bar
+      // at 1 pixel so user can see and hover over to see the data.
+      return (ht < 0) ? 1 : ht;
     };
     var getBarPos = (d) {
       var scaledVal = measureScale.scale(d).round();
+
+      // If bar would be scaled to 0 height but data is not 0, reserve 1 pixel
+      // height plus strokeWidthOffset to position the bar.
+      if (scaledVal == scaled0) {
+        return verticalBars
+            ? d > 0
+                ? scaled0 - 1 - strokeWidthOffset
+                : scaled0 + strokeWidthOffset
+            : d > 0
+                ? scaled0 + strokeWidthOffset
+                : scaled0 - 1 - strokeWidthOffset;
+      }
       return verticalBars
           ? (d >= 0 ? scaledVal : scaled0) + strokeWidthOffset
           : (d >= 0 ? scaled0 : scaledVal) + strokeWidthOffset;
     };
     var buildPath = (d, int i, bool animate) {
+      // If data is null or 0, an empty path for the bar is returned directly.
       if (d == null || d == 0) return '';
       if (verticalBars) {
         var fn = d > 0 ? topRoundedRect : bottomRoundedRect;
diff --git a/packages/charted/lib/charts/cartesian_renderers/bubble_chart_renderer.dart b/packages/charted/lib/charts/cartesian_renderers/bubble_chart_renderer.dart
index b05dd81..65042de 100644
--- a/packages/charted/lib/charts/cartesian_renderers/bubble_chart_renderer.dart
+++ b/packages/charted/lib/charts/cartesian_renderers/bubble_chart_renderer.dart
@@ -71,7 +71,7 @@
     group.enter.append('g')..classed('measure-group');
     group.each((d, i, e) {
       e.style.setProperty('fill', color(i));
-      e.attributes['data-column'] = series.measures.elementAt(i);
+      e.attributes['data-column'] = series.measures.elementAt(i).toString();
     });
     group.exit.remove();
 
@@ -85,7 +85,7 @@
             '${xDimensionScale.scale(xDimensionVals[i])},'
             '${yDimensionScale.scale(yDimensionVals[i])})'
         ..['r'] = '${bubbleRadiusScale.scale(d) * bubbleRadiusFactor}'
-        ..['data-row'] = i;
+        ..['data-row'] = i.toString();
     });
     measures.exit.remove();
     handleStateChanges([]);
@@ -107,7 +107,9 @@
   @override
   Extent get extent {
     assert(series != null && area != null);
-    var rows = area.data.rows, max = rows[0][series.measures.first], min = max;
+    var rows = area.data.rows,
+        max = rows.first[series.measures.first],
+        min = max;
 
     rows.forEach((row) {
       series.measures.forEach((idx) {
diff --git a/packages/charted/lib/charts/cartesian_renderers/cartesian_base_renderer.dart b/packages/charted/lib/charts/cartesian_renderers/cartesian_base_renderer.dart
index 96873bd..92ccbd6 100644
--- a/packages/charted/lib/charts/cartesian_renderers/cartesian_base_renderer.dart
+++ b/packages/charted/lib/charts/cartesian_renderers/cartesian_base_renderer.dart
@@ -182,7 +182,7 @@
       if (state == null || area.useRowColoring) {
         _columnStylesCache[column] = const [];
       } else {
-        var styles = [], flags = _columnStateCache[column];
+        var styles = <String>[], flags = _columnStateCache[column];
 
         if (flags & ChartState.COL_SELECTED != 0) {
           styles.add(ChartState.COL_SELECTED_CLASS);
diff --git a/packages/charted/lib/charts/cartesian_renderers/line_chart_renderer.dart b/packages/charted/lib/charts/cartesian_renderers/line_chart_renderer.dart
index e67fcaa..4806d2d 100644
--- a/packages/charted/lib/charts/cartesian_renderers/line_chart_renderer.dart
+++ b/packages/charted/lib/charts/cartesian_renderers/line_chart_renderer.dart
@@ -10,7 +10,6 @@
 
 class LineChartRenderer extends CartesianRendererBase {
   final Iterable<int> dimensionsUsingBand = const [];
-  final SubscriptionsDisposer _disposer = new SubscriptionsDisposer();
 
   final bool alwaysAnimate;
   final bool trackDataPoints;
@@ -249,7 +248,7 @@
     }
   }
 
-  void _mouseOverHandler(d, i, e) {
+  void _mouseOverHandler(d, int i, Element e) {
     if (area.state != null) {
       area.state.preview = int.parse(e.dataset['column']);
     }
@@ -261,7 +260,7 @@
     }
   }
 
-  void _mouseOutHandler(d, i, e) {
+  void _mouseOutHandler(d, int i, Element e) {
     if (area.state != null &&
         area.state.preview == int.parse(e.dataset['column'])) {
       area.state.preview = null;
diff --git a/packages/charted/lib/charts/cartesian_renderers/stackedbar_chart_renderer.dart b/packages/charted/lib/charts/cartesian_renderers/stackedbar_chart_renderer.dart
index 05623ba..0d26675 100644
--- a/packages/charted/lib/charts/cartesian_renderers/stackedbar_chart_renderer.dart
+++ b/packages/charted/lib/charts/cartesian_renderers/stackedbar_chart_renderer.dart
@@ -26,7 +26,11 @@
   /// Returns false if the number of dimension axes on the area is 0.
   /// Otherwise, the first dimension scale is used to render the chart.
   @override
-  bool prepare(CartesianArea area, ChartSeries series) {
+  bool prepare(ChartArea area, ChartSeries series) {
+    if (area is! CartesianArea) {
+      throw new ArgumentError.value(area, 'area',
+          "ChartArea for StackedBarChartRenderer must be a CartesianArea");
+    }
     _ensureAreaAndSeries(area, series);
     return true;
   }
@@ -89,7 +93,8 @@
       });
     }
 
-    var barWidth = dimensionScale.rangeBand - theme.defaultStrokeWidth;
+    var barWidth =
+        (dimensionScale as OrdinalScale).rangeBand - theme.defaultStrokeWidth;
 
     // Calculate height of each segment in the bar.
     // Uses prevAllZeroHeight and prevOffset to track previous segments
diff --git a/packages/charted/lib/charts/chart_data.dart b/packages/charted/lib/charts/chart_data.dart
index de58dbc..1367cc1 100644
--- a/packages/charted/lib/charts/chart_data.dart
+++ b/packages/charted/lib/charts/chart_data.dart
@@ -17,7 +17,7 @@
   Iterable<ChartColumnSpec> get columns;
 
   /// Read-only access to rows
-  Iterable<Iterable> get rows;
+  Iterable<List> get rows;
 
   /// Create a new instance of [ChartData]'s internal implementation
   factory ChartData(Iterable<ChartColumnSpec> columns,
diff --git a/packages/charted/lib/charts/chart_events.dart b/packages/charted/lib/charts/chart_events.dart
index 5e0deff..49a7a66 100644
--- a/packages/charted/lib/charts/chart_events.dart
+++ b/packages/charted/lib/charts/chart_events.dart
@@ -82,7 +82,10 @@
   num get chartY;
 
   factory ChartEvent(Event source, ChartArea area,
-      [ChartSeries series, int row, int column, value]) = DefaultChartEventImpl;
+      [ChartSeries series,
+      int row,
+      int column,
+      num value]) = DefaultChartEventImpl;
 }
 
 /// Interface implemented by chart behaviors.
diff --git a/packages/charted/lib/charts/chart_state.dart b/packages/charted/lib/charts/chart_state.dart
index 7909ada..3b05e84 100644
--- a/packages/charted/lib/charts/chart_state.dart
+++ b/packages/charted/lib/charts/chart_state.dart
@@ -35,7 +35,7 @@
   static const VAL_UNHIGHLIGHTED_CLASS = 'row-unhighlighted';
   static const VAL_HOVERED_CLASS = 'row-hovered';
 
-  static const COLUMN_CLASS_NAMES = const [
+  static const COLUMN_CLASS_NAMES = const <String>[
     COL_SELECTED_CLASS,
     COL_UNSELECTED_CLASS,
     COL_PREVIEW_CLASS,
@@ -45,7 +45,7 @@
     COL_HOVERED_CLASS
   ];
 
-  static const VALUE_CLASS_NAMES = const [
+  static const VALUE_CLASS_NAMES = const <String>[
     COL_SELECTED_CLASS,
     COL_UNSELECTED_CLASS,
     COL_PREVIEW_CLASS,
@@ -76,7 +76,7 @@
 
   /// Currently highlighted value, if any, represented as column and row.
   /// Highlight is result of a click on certain value.
-  Iterable<Pair<int, int>> highlights;
+  Iterable<Pair<int, int>> get highlights;
 
   /// Currently hovered value, if any, represented as column and row.
   /// Hover is result of mouse moving over a certian value in chart.
diff --git a/packages/charted/lib/charts/chart_theme.dart b/packages/charted/lib/charts/chart_theme.dart
index 1515f87..1e49a4e 100644
--- a/packages/charted/lib/charts/chart_theme.dart
+++ b/packages/charted/lib/charts/chart_theme.dart
@@ -30,7 +30,7 @@
 
   /// Markup for filters that is added to all chart elements. These filters
   /// can be referenced using url() in values returned by [getFilterForState].
-  String filters;
+  String get filters;
 
   /// Returns any filters that must be applied based on the element's state
   String getFilterForState(int state);
@@ -119,8 +119,10 @@
   /// visualization.
   int get verticalAxisWidth => 200;
 
-  /// Height of horizontal axis. Width of horizontal axis is automatically
-  /// computed based on width of the visualization.
+  /// Max height of horizontal axis, this is used when the axis label need to be
+  /// rotated.  If rotated label would be ellipsed if the height is greater than
+  /// this value. Width of horizontal axis is automatically computed based on
+  /// width of the visualization.
   int get horizontalAxisHeight => 200;
 
   /// Font used by axis ticks. When specified, axis uses efficient off-screen
diff --git a/packages/charted/lib/charts/charts.dart b/packages/charted/lib/charts/charts.dart
index 4279143..3d00cf6 100644
--- a/packages/charted/lib/charts/charts.dart
+++ b/packages/charted/lib/charts/charts.dart
@@ -10,7 +10,7 @@
 
 import 'dart:async';
 import 'dart:collection';
-import 'dart:html' show Element, document, window, Event, MouseEvent;
+import 'dart:html' show Element, window, Event, MouseEvent;
 import 'dart:math' as math;
 import 'dart:svg' hide Rect;
 import 'dart:typed_data';
diff --git a/packages/charted/lib/charts/data_transformers/aggregation.dart b/packages/charted/lib/charts/data_transformers/aggregation.dart
index 1efe921..3cef348 100644
--- a/packages/charted/lib/charts/data_transformers/aggregation.dart
+++ b/packages/charted/lib/charts/data_transformers/aggregation.dart
@@ -11,6 +11,8 @@
 ///Function callback to filter items in the input
 typedef bool AggregationFilterFunc(var item);
 
+typedef int CompareFunc(dynamic a, dynamic b);
+
 typedef dynamic FieldAccessor(dynamic item, dynamic key);
 
 /// Given list of items, dimensions and facts, compute
@@ -89,7 +91,7 @@
   final bool walkThroughMap;
 
   // Map of fieldName to comparator function.
-  final Map<String, Function> comparators;
+  final Map<String, CompareFunc> comparators;
 
   // Timing operations
   static final Logger _logger = new Logger('aggregations');
@@ -102,10 +104,10 @@
   /// Create a new [AggregationModel] from a [collection] of items,
   /// list of [dimensions] on which the items are grouped and a list of [facts]
   /// on which aggregations are computed.
-  AggregationModel(List collection, List dimensions, List facts,
+  AggregationModel(Iterable collection, List dimensions, List facts,
       {List<String> aggregationTypes,
       this.walkThroughMap: false,
-      this.comparators,
+      this.comparators: const <String, CompareFunc>{},
       this.dimensionAccessor,
       this.factsAccessor}) {
     _init(collection, dimensions, facts, aggregationTypes);
@@ -127,7 +129,7 @@
   List get dimensionFields => _dimFields;
 
   /// Initialize the view
-  void _init(List collection, List dimensions, List facts,
+  void _init(Iterable collection, List dimensions, List facts,
       List<String> aggregationTypes) {
     if (collection == null) {
       throw new ArgumentError('Data cannot be empty or null');
@@ -165,7 +167,7 @@
       aggregationTypes.add('valid');
     }
 
-    _rows = collection;
+    _rows = new List.from(collection, growable: false);
     _dimFields = new List.from(dimensions, growable: false);
     _factFields = new List.from(facts, growable: false);
     _entityCache = new Map<String, AggregationItem>();
@@ -270,6 +272,7 @@
   }
 
   final Map<String, List> _parsedKeys = {};
+
   /// Get value from a map-like object
   dynamic _fetch(var item, String key) {
     if (walkThroughMap && key.contains('.')) {
@@ -327,21 +330,22 @@
     // Sort all dimensions internally
     // The resulting arrays would be used to sort the entire data
 
-    List oldSortOrders = _dimSortOrders;
+    List<List<int>> oldSortOrders = _dimSortOrders;
     _dimSortOrders = new List.generate(dimensionsCount, (i) {
       if (groupBy && i < _dimPrefixLength) {
         return oldSortOrders[i];
       }
 
       List dimensionVals = new List.from(_dimToIntMap[i].keys);
-      List retval = new List(_dimToIntMap[i].length);
+      List<int> retval = new List<int>(_dimToIntMap[i].length);
 
       // When a comparator is not specified, our implementation of the
       // comparator tries to gracefully handle null values.
-      dimensionVals.sort(
-          comparators != null && comparators.containsKey(_dimFields[i])
-              ? comparators[_dimFields[i]]
-              : _defaultDimComparator);
+      if (comparators.containsKey(_dimFields[i])) {
+        dimensionVals.sort(comparators[_dimFields[i]]);
+      } else {
+        dimensionVals.sort(_defaultDimComparator);
+      }
 
       for (int si = 0; si < retval.length; ++si) {
         retval[_dimToIntMap[i][dimensionVals[si]]] = si;
@@ -364,14 +368,14 @@
   }
 
   // Ensures that null dimension values don't cause an issue with sorting
-  _defaultDimComparator(Comparable left, Comparable right) =>
+  int _defaultDimComparator(Comparable left, Comparable right) =>
       (left == null && right == null)
           ? 0
           : (left == null) ? -1 : (right == null) ? 1 : left.compareTo(right);
 
   /// Given item indices in rows, compare them based
   /// on the sort orders created while pre-processing data.
-  _comparator(int one, int two) {
+  int _comparator(int one, int two) {
     if (one == two) {
       return 0;
     }
@@ -549,7 +553,7 @@
   /// Callers of this method can observe the returned entity for updates to
   /// aggregations caused by changes to filter or done through add, remove
   /// or modify of items in the collection.
-  AggregationItem facts(List dimension) {
+  AggregationItem facts(List<String> dimension) {
     List<int> enumeratedList = new List<int>();
     for (int i = 0; i < dimension.length; ++i) {
       enumeratedList.add(_dimToIntMap[i][dimension[i]]);
@@ -573,10 +577,11 @@
       return null;
     }
     List values = new List.from(_dimToIntMap[di].keys);
-    values.sort(
-        comparators != null && comparators.containsKey(dimensionFieldName)
-            ? comparators[dimensionFieldName]
-            : _defaultDimComparator);
+    if (comparators.containsKey(dimensionFieldName)) {
+      values.sort(comparators[dimensionFieldName]);
+    } else {
+      values.sort(_defaultDimComparator);
+    }
     return values;
   }
 }
diff --git a/packages/charted/lib/charts/data_transformers/aggregation_item.dart b/packages/charted/lib/charts/data_transformers/aggregation_item.dart
index 1c9f564..5ac5b56 100644
--- a/packages/charted/lib/charts/data_transformers/aggregation_item.dart
+++ b/packages/charted/lib/charts/data_transformers/aggregation_item.dart
@@ -28,6 +28,9 @@
   /// are supported as the operators.
   operator [](String key);
 
+  /// List of lower aggregations.
+  List<AggregationItem> lowerAggregations();
+
   /// Check if we support a given key.
   bool containsKey(String key);
 
@@ -132,13 +135,10 @@
     if (key == 'items') {
       return new _AggregationItemsIterator(model, dimensions, _key);
     }
-    if (key == 'aggregations') {
-      return _lowerAggregations();
-    }
     return null;
   }
 
-  List<AggregationItem> _lowerAggregations() {
+  List<AggregationItem> lowerAggregations() {
     List<AggregationItem> aggregations = new List<AggregationItem>();
     if (dimensions.length == model._dimFields.length) {
       return aggregations;
@@ -148,7 +148,7 @@
     List lowerVals = model.valuesForDimension(lowerDimensionField);
 
     lowerVals.forEach((name) {
-      List lowerDims = new List.from(dimensions)..add(name);
+      List<String> lowerDims = new List.from(dimensions)..add(name);
       AggregationItem entity = model.facts(lowerDims);
       if (entity != null) {
         aggregations.add(entity);
diff --git a/packages/charted/lib/charts/data_transformers/aggregation_transformer.dart b/packages/charted/lib/charts/data_transformers/aggregation_transformer.dart
index 7cd8028..0c5af4f 100644
--- a/packages/charted/lib/charts/data_transformers/aggregation_transformer.dart
+++ b/packages/charted/lib/charts/data_transformers/aggregation_transformer.dart
@@ -26,8 +26,8 @@
   static const String AGGREGATION_TYPE_VALID = 'valid';
   final SubscriptionsDisposer _dataSubscriptions = new SubscriptionsDisposer();
   final Set<List> _expandedSet = new Set();
-  Iterable<ChartColumnSpec> columns;
-  ObservableList<Iterable> rows = new ObservableList();
+  List<ChartColumnSpec> columns;
+  ObservableList<List> rows = new ObservableList<List>();
   List<int> _dimensionColumnIndices;
   List<int> _factsColumnIndices;
   String _aggregationType;
@@ -91,7 +91,7 @@
 
     // Process rows.
     rows.clear();
-    var transformedRows = <Iterable>[];
+    var transformedRows = <List>[];
     for (var value in _model.valuesForDimension(_dimensionColumnIndices[0])) {
       _generateAggregatedRow(transformedRows, [value]);
     }
@@ -107,7 +107,8 @@
   /// generated for its children but not for itself.  If we want to change the
   /// logic to include itself, just move the expand check around the else clause
   /// and always write a row of data whether it's expanded or not.
-  _generateAggregatedRow(List<Iterable> aggregatedRows, List dimensionValues) {
+  _generateAggregatedRow(
+      List<List> aggregatedRows, List<String> dimensionValues) {
     var entity = _model.facts(dimensionValues);
     var dimensionLevel = dimensionValues.length - 1;
 
@@ -136,7 +137,7 @@
     } else {
       // Dimension is expanded, process each child dimension in the expanded
       // dimension.
-      for (AggregationItem childAggregation in entity['aggregations']) {
+      for (AggregationItem childAggregation in entity.lowerAggregations()) {
         _generateAggregatedRow(aggregatedRows, childAggregation.dimensions);
       }
     }
@@ -187,10 +188,10 @@
     }
   }
 
-  void _expandAll(value) {
+  void _expandAll(List<String> value) {
     var entity = _model.facts(value);
     _expandedSet.add(value);
-    for (AggregationItem childAggregation in entity['aggregations']) {
+    for (AggregationItem childAggregation in entity.lowerAggregations()) {
       _expandAll(childAggregation.dimensions);
     }
   }
diff --git a/packages/charted/lib/charts/data_transformers/filter_transformer.dart b/packages/charted/lib/charts/data_transformers/filter_transformer.dart
index bc12597..cc002ea 100644
--- a/packages/charted/lib/charts/data_transformers/filter_transformer.dart
+++ b/packages/charted/lib/charts/data_transformers/filter_transformer.dart
@@ -17,8 +17,8 @@
 class FilterTransformer extends ChangeNotifier
     implements ChartDataTransform, ChartData {
   final SubscriptionsDisposer _dataSubscriptions = new SubscriptionsDisposer();
-  Iterable<ChartColumnSpec> columns;
-  ObservableList<Iterable> rows = new ObservableList();
+  List<ChartColumnSpec> columns;
+  ObservableList<List> rows = new ObservableList();
   List<FilterDefinition> filterFunctions;
   ChartData _data;
 
diff --git a/packages/charted/lib/charts/data_transformers/transpose_transformer.dart b/packages/charted/lib/charts/data_transformers/transpose_transformer.dart
index fcab1a0..d1cad14 100644
--- a/packages/charted/lib/charts/data_transformers/transpose_transformer.dart
+++ b/packages/charted/lib/charts/data_transformers/transpose_transformer.dart
@@ -21,7 +21,7 @@
     implements ChartDataTransform, ChartData {
   final SubscriptionsDisposer _dataSubscriptions = new SubscriptionsDisposer();
   ObservableList<ChartColumnSpec> columns = new ObservableList();
-  ObservableList<Iterable> rows = new ObservableList();
+  ObservableList<List> rows = new ObservableList();
 
   // If specified, this values of this column in the input chart data will be
   // used as labels of the transposed column label.  Defaults to first column.
@@ -64,7 +64,7 @@
     // Assert all columns are of the same type and formatter, excluding the
     // label column.
     var type;
-    var formatter;
+    FormatFunction formatter;
     for (var i = 0; i < _data.columns.length; i++) {
       if (i != _labelColumn) {
         if (type == null) {
@@ -82,8 +82,7 @@
 
     columns.clear();
     rows.clear();
-    rows.addAll(
-        new List<Iterable>.generate(_data.columns.length - 1, (i) => []));
+    rows.addAll(new List<List>.generate(_data.columns.length - 1, (i) => []));
 
     // Populate the transposed rows' data, excluding the label column, visit
     // each value in the original data once.
@@ -92,7 +91,7 @@
       for (var i = 0; i < row.length; i++) {
         var columnOffset = (i < _labelColumn) ? 0 : 1;
         if (i != _labelColumn) {
-          (rows.elementAt(i - columnOffset) as List).add(row.elementAt(i));
+          rows.elementAt(i - columnOffset).add(row.elementAt(i));
         } else {
           columnLabels.add(row.elementAt(i));
         }
@@ -103,7 +102,7 @@
     // column that is used as the new label.
     for (var i = 0; i < rows.length; i++) {
       var columnOffset = (i < _labelColumn) ? 0 : 1;
-      (rows.elementAt(i) as List).insert(
+      rows.elementAt(i).insert(
           _labelColumn, _data.columns.elementAt(i + columnOffset).label);
     }
 
diff --git a/packages/charted/lib/charts/layout_renderers/layout_base_renderer.dart b/packages/charted/lib/charts/layout_renderers/layout_base_renderer.dart
index 35bfbcc..a104182 100644
--- a/packages/charted/lib/charts/layout_renderers/layout_base_renderer.dart
+++ b/packages/charted/lib/charts/layout_renderers/layout_base_renderer.dart
@@ -123,7 +123,7 @@
       if (state == null) {
         _valueStylesCache[row] = const [];
       } else {
-        var styles = [], flags = _valueStateCache[row];
+        var styles = <String>[], flags = _valueStateCache[row];
 
         if (flags & ChartState.VAL_HIGHLIGHTED != 0) {
           styles.add(ChartState.VAL_HIGHLIGHTED_CLASS);
diff --git a/packages/charted/lib/charts/layout_renderers/pie_chart_renderer.dart b/packages/charted/lib/charts/layout_renderers/pie_chart_renderer.dart
index 4409469..e32470d 100644
--- a/packages/charted/lib/charts/layout_renderers/pie_chart_renderer.dart
+++ b/packages/charted/lib/charts/layout_renderers/pie_chart_renderer.dart
@@ -98,43 +98,56 @@
       indices = indices.reversed.toList();
     }
 
-    var accessor = (d, i) {
+    num accessor(d, int i) {
       var row = d == SMALL_INT_MAX ? otherRow : area.data.rows.elementAt(d);
       return row == null || row.elementAt(measure) == null
           ? 0
-          : row.elementAt(measure);
-    };
-    var data = (new PieLayout()..accessor = accessor).layout(indices),
-        arc = new SvgArc(
-            innerRadiusCallback: (d, i, e) => innerRadiusRatio * radius,
-            outerRadiusCallback: (d, i, e) => radius),
-        pie = root.selectAll('.pie-path').data(data);
+          : row.elementAt(measure) as num;
+    }
+    var data = (new PieLayout()..accessor = accessor).layout(indices);
+    var arc = new SvgArc(
+        innerRadiusCallback: (d, i, e) => innerRadiusRatio * radius,
+        outerRadiusCallback: (d, i, e) => radius);
+    var pie = root.selectAll('.pie-path').data(data);
 
-    pie.enter.append('path').classed('pie-path');
-    pie
-      ..each((d, i, e) {
-        var styles = stylesForData(d.data, i);
-        e.classes.removeAll(ChartState.VALUE_CLASS_NAMES);
-        if (!isNullOrEmpty(styles)) {
-          e.classes.addAll(styles);
-        }
-        e.attributes
-          ..['fill'] = colorForData(d.data, i)
-          ..['d'] = arc.path(d, i, host)
-          ..['stroke-width'] = '1px'
-          ..['stroke'] = '#ffffff';
+    pie.enter.appendWithCallback((d, i, e) {
+      var pieSector = Namespace.createChildElement('path', e)
+        ..classes.add('pie-path');
+      var styles = stylesForData(d.data, i);
+      if (!isNullOrEmpty(styles)) {
+        pieSector.classes.addAll(styles);
+      }
+      pieSector.attributes
+        ..['fill'] = colorForData(d.data, i)
+        ..['d'] = arc.path(d, i, host)
+        ..['stroke-width'] = '1px'
+        ..['stroke'] = '#ffffff';
 
-        e.append(
-            Namespace.createChildElement('text', e)..classes.add('pie-label'));
-      })
+      pieSector.append(Namespace.createChildElement('text', pieSector)
+        ..classes.add('pie-label'));
+      return pieSector;
+    })
       ..on('click', (d, i, e) => _event(mouseClickController, d, i, e))
       ..on('mouseover', (d, i, e) => _event(mouseOverController, d, i, e))
       ..on('mouseout', (d, i, e) => _event(mouseOutController, d, i, e));
 
+    pie.each((d, i, e) {
+      var styles = stylesForData(d.data, i);
+      e.classes.removeAll(ChartState.VALUE_CLASS_NAMES);
+      if (!isNullOrEmpty(styles)) {
+        e.classes.addAll(styles);
+      }
+      e.attributes
+        ..['fill'] = colorForData(d.data, i)
+        ..['d'] = arc.path(d, i, host)
+        ..['stroke-width'] = '1px'
+        ..['stroke'] = '#ffffff';
+    });
+
     pie.exit.remove();
 
     _legend.clear();
-    var items = new List.generate(data.length, (i) {
+    var items = new List<ChartLegendItem>.generate(data.length, (i) {
       SvgArcData d = data.elementAt(i);
       Iterable row =
           d.data == SMALL_INT_MAX ? otherRow : area.data.rows.elementAt(d.data);
diff --git a/packages/charted/lib/charts/src/cartesian_area_impl.dart b/packages/charted/lib/charts/src/cartesian_area_impl.dart
index 8138873..870971a 100644
--- a/packages/charted/lib/charts/src/cartesian_area_impl.dart
+++ b/packages/charted/lib/charts/src/cartesian_area_impl.dart
@@ -13,7 +13,7 @@
 /// which contain two dimension axes.
 class DefaultCartesianAreaImpl implements CartesianArea {
   /// Default identifiers used by the measure axes
-  static const MEASURE_AXIS_IDS = const ['_default'];
+  static const MEASURE_AXIS_IDS = const <String>['_default'];
 
   /// Orientations used by measure axes. First, when "x" axis is the primary
   /// and the only dimension. Second, when "y" axis is the primary and the only
@@ -117,7 +117,7 @@
   void dispose() {
     _configEventsDisposer.dispose();
     _dataEventsDisposer.dispose();
-    _config.legend.dispose();
+    _config?.legend?.dispose();
 
     if (_valueMouseOverController != null) {
       _valueMouseOverController.close();
@@ -349,7 +349,6 @@
   }
 
   String _orientRTL(String orientation) => orientation;
-  Scale _scaleRTL(Scale scale) => scale;
 
   /// Initialize the axes - required even if the axes are not being displayed.
   _initAxes({bool preRender: false}) {
@@ -376,8 +375,8 @@
     measureAxisUsers.forEach((id, listOfSeries) {
       var sampleCol = listOfSeries.first.measures.first,
           sampleColSpec = data.columns.elementAt(sampleCol),
-          axis = _getMeasureAxis(id),
-          domain;
+          axis = _getMeasureAxis(id);
+      List domain;
 
       if (sampleColSpec.useOrdinalScale) {
         throw new UnsupportedError(
@@ -561,12 +560,13 @@
     if (_config == null || _config.legend == null || _series.isEmpty) return;
 
     var legend = <ChartLegendItem>[];
-    List seriesByColumn =
-        new List.generate(data.columns.length, (_) => new List());
+    List<List<ChartSeries>> seriesByColumn =
+        new List<List<ChartSeries>>.generate(
+            data.columns.length, (_) => <ChartSeries>[]);
 
     _series.forEach((s) => s.measures.forEach((m) => seriesByColumn[m].add(s)));
 
-    seriesByColumn.asMap().forEach((int i, List s) {
+    seriesByColumn.asMap().forEach((int i, List<ChartSeries> s) {
       if (s.length == 0) return;
       legend.add(new ChartLegendItem(
           index: i,
@@ -664,10 +664,10 @@
   get axes => _axesView;
 
   @override
-  Rect renderArea;
+  Rect renderArea = const Rect();
 
   @override
-  Rect chartArea;
+  Rect chartArea = const Rect();
 
   _ChartAreaLayout() {
     _axesView = new UnmodifiableMapView(_axes);
diff --git a/packages/charted/lib/charts/src/chart_axis_impl.dart b/packages/charted/lib/charts/src/chart_axis_impl.dart
index 345d537..4a684b3 100644
--- a/packages/charted/lib/charts/src/chart_axis_impl.dart
+++ b/packages/charted/lib/charts/src/chart_axis_impl.dart
@@ -83,17 +83,16 @@
         : new MutableRect.size(layout.height, _theme.horizontalAxisHeight);
 
     // Handle auto re-sizing of horizontal axis.
+    var ticks = (_config != null && !isNullOrEmpty(_config.tickValues))
+        ? _config.tickValues
+        : scale.ticks,
+    formatter = _columnSpec.formatter == null
+        ? scale.createTickFormatter()
+        : _columnSpec.formatter,
+    textMetrics = new TextMetrics(fontStyle: _theme.ticksFont),
+    formattedTicks = ticks.map((x) => formatter(x)).toList(),
+    shortenedTicks = formattedTicks;
     if (_isVertical) {
-      var ticks = (_config != null && !isNullOrEmpty(_config.tickValues))
-              ? _config.tickValues
-              : scale.ticks,
-          formatter = _columnSpec.formatter == null
-              ? scale.createTickFormatter()
-              : _columnSpec.formatter,
-          textMetrics = new TextMetrics(fontStyle: _theme.ticksFont),
-          formattedTicks = ticks.map((x) => formatter(x)).toList(),
-          shortenedTicks = formattedTicks;
-
       var width = textMetrics.getLongestTextWidth(formattedTicks).ceil();
       if (width > _theme.verticalAxisWidth) {
         width = _theme.verticalAxisWidth;
@@ -105,8 +104,20 @@
         size.width =
             width + _theme.axisTickPadding + math.max(_theme.axisTickSize, 0);
       }
+
       _axisTicksPlacement =
           new PrecomputedAxisTicks(ticks, formattedTicks, shortenedTicks);
+    } else {
+      // Precompute if extra room is needed for rotated label.
+      var width = layout.width -
+          _area.layout.axes[ORIENTATION_LEFT].width -
+          _area.layout.axes[ORIENTATION_RIGHT].width;
+      var allowedWidth = width ~/ ticks.length,
+          maxLabelWidth = textMetrics.getLongestTextWidth(formattedTicks);
+      if (!RotateHorizontalAxisTicks.needsLabelRotation(
+          allowedWidth, maxLabelWidth)) {
+        size.height = textMetrics.fontSize * 2;
+      }
     }
   }
 
@@ -151,7 +162,9 @@
   Scale get scale =>
       (_config != null && _config.scale != null) ? _config.scale : _scale;
 
-  set scale(Scale value) => _scale = value;
+  set scale(Scale value) {
+    _scale = value;
+  }
 }
 
 class PrecomputedAxisTicks implements SvgAxisTicks {
@@ -171,11 +184,14 @@
 
   int rotation = 0;
   Iterable ticks;
-  Iterable formattedTicks;
+  Iterable<String> formattedTicks;
   Iterable shortenedTicks;
 
   RotateHorizontalAxisTicks(this.rect, this.ticksFont, this.tickLineLength);
 
+  static bool needsLabelRotation(num allowedWidth, num maxLabelWidth) =>
+      0.90 * allowedWidth < maxLabelWidth;
+
   void init(SvgAxis axis) {
     assert(axis.orientation == ORIENTATION_BOTTOM ||
         axis.orientation == ORIENTATION_TOP);
@@ -190,7 +206,7 @@
         maxLabelWidth = textMetrics.getLongestTextWidth(formattedTicks);
 
     // Check if we need rotation
-    if (0.90 * allowedWidth < maxLabelWidth) {
+    if (needsLabelRotation(allowedWidth, maxLabelWidth)) {
       var rectHeight =
           tickLineLength > 0 ? rect.height - tickLineLength : rect.height;
       rotation = 45;
diff --git a/packages/charted/lib/charts/src/chart_config_impl.dart b/packages/charted/lib/charts/src/chart_config_impl.dart
index 640d23f..80bedaf 100644
--- a/packages/charted/lib/charts/src/chart_config_impl.dart
+++ b/packages/charted/lib/charts/src/chart_config_impl.dart
@@ -57,7 +57,8 @@
     values.forEach((item) {
       if (item is Observable) {
         _disposer.add(
-            item.changes
+            (item as Observable)
+                .changes
                 .listen((_) => notifyChange(const ChartConfigChangeRecord())),
             item);
       }
diff --git a/packages/charted/lib/charts/src/chart_data_impl.dart b/packages/charted/lib/charts/src/chart_data_impl.dart
index dff6f5c..2dc6ed0 100644
--- a/packages/charted/lib/charts/src/chart_data_impl.dart
+++ b/packages/charted/lib/charts/src/chart_data_impl.dart
@@ -9,16 +9,18 @@
 part of charted.charts;
 
 class DefaultChartDataImpl extends ChangeNotifier implements ChartData {
-  Iterable<ChartColumnSpec> _columns;
-  Iterable<Iterable> _rows;
+  List<ChartColumnSpec> _columns;
+  List<List> _rows;
 
   bool _hasObservableRows = false;
   SubscriptionsDisposer _disposer = new SubscriptionsDisposer();
 
   DefaultChartDataImpl(
       Iterable<ChartColumnSpec> columns, Iterable<Iterable> rows) {
-    this.columns = columns;
-    this.rows = rows;
+    this.columns = new List<ChartColumnSpec>.from(columns);
+    var rowsList = new List.from(rows);
+    this.rows = new List<List>.generate(
+        rowsList.length, (i) => new List.from(rowsList[i]));
   }
 
   set columns(Iterable<ChartColumnSpec> value) {
@@ -30,9 +32,9 @@
     this._columns = new List<ChartColumnSpec>.from(value);
   }
 
-  Iterable<ChartColumnSpec> get columns => _columns;
+  List<ChartColumnSpec> get columns => _columns;
 
-  set rows(Iterable<Iterable> value) {
+  set rows(List<List> value) {
     assert(value != null);
 
     _rows = value;
@@ -45,7 +47,9 @@
       for (int i = 0; i < _rows.length; i++) {
         var row = _rows.elementAt(i);
         _disposer.add(
-            row.listChanges.listen((changes) => _valuesChanged(i, changes)),
+            (row as ObservableList)
+                .listChanges
+                .listen((changes) => _valuesChanged(i, changes)),
             row);
       }
       ;
@@ -54,7 +58,7 @@
     }
   }
 
-  Iterable<Iterable> get rows => _rows;
+  List<List> get rows => _rows;
 
   rowsChanged(List<ListChangeRecord> changes) {
     if (_rows is! ObservableList) return;
@@ -72,7 +76,7 @@
               'Changes on this row will not be monitored');
         } else {
           _disposer.add(
-              row.listChanges
+              (row as ObservableList).listChanges
                   .listen((changes) => _valuesChanged(index, changes)),
               row);
         }
diff --git a/packages/charted/lib/charts/src/chart_events_impl.dart b/packages/charted/lib/charts/src/chart_events_impl.dart
index 9bb8d1e..d98ceca 100644
--- a/packages/charted/lib/charts/src/chart_events_impl.dart
+++ b/packages/charted/lib/charts/src/chart_events_impl.dart
@@ -16,7 +16,7 @@
   final ChartSeries series;
 
   @override
-  final MouseEvent source;
+  final Event source;
 
   @override
   final int column;
@@ -38,9 +38,10 @@
     var hostRect = area.host.getBoundingClientRect(),
         left =
         area.config.isRTL ? area.theme.padding.end : area.theme.padding.start;
-    if (source != null) {
-      chartX = source.client.x - hostRect.left - left;
-      chartY = source.client.y - hostRect.top - area.theme.padding.top;
+    if (source is MouseEvent) {
+      MouseEvent mouseSource = source;
+      chartX = mouseSource.client.x - hostRect.left - left;
+      chartY = mouseSource.client.y - hostRect.top - area.theme.padding.top;
     }
   }
 }
diff --git a/packages/charted/lib/charts/src/chart_legend_impl.dart b/packages/charted/lib/charts/src/chart_legend_impl.dart
index dfefbc4..7f3389e 100644
--- a/packages/charted/lib/charts/src/chart_legend_impl.dart
+++ b/packages/charted/lib/charts/src/chart_legend_impl.dart
@@ -114,7 +114,7 @@
         _root.selectAll('.chart-legend-row').data(_items, (x) => x.hashCode),
         isFirstRender = rows.length == 0;
 
-    var enter = rows.enter.appendWithCallback((d, i, e) {
+    var enter = rows.enter.appendWithCallback((ChartLegendItem d, i, e) {
       var row = Namespace.createChildElement('div', e),
           color = Namespace.createChildElement('div', e)
             ..className = 'chart-legend-color',
@@ -125,7 +125,7 @@
                 ..className = 'chart-legend-value')
               : null;
 
-      var rowStyles = ['chart-legend-row'].toList();
+      var rowStyles = <String>['chart-legend-row'];
 
       // If this is the first time we are adding rows,
       // Update elements before adding them to the DOM.
@@ -205,5 +205,5 @@
   }
 
   /// Update legend to show chart's selection and visibility.
-  void _handleStateChanges(_) => _createLegendItems();
+  void _handleStateChanges(List<ChangeRecord> _) => _createLegendItems();
 }
diff --git a/packages/charted/lib/charts/src/chart_series_impl.dart b/packages/charted/lib/charts/src/chart_series_impl.dart
index 3fe88b9..5bbabd2 100644
--- a/packages/charted/lib/charts/src/chart_series_impl.dart
+++ b/packages/charted/lib/charts/src/chart_series_impl.dart
@@ -43,10 +43,13 @@
 
   Iterable<int> get measures => _measures;
 
-  set measureAxisIds(Iterable<String> value) => _measureAxisIds = value;
+  set measureAxisIds(Iterable<String> value) {
+    _measureAxisIds = value;
+  }
+
   Iterable<String> get measureAxisIds => _measureAxisIds;
 
-  _measuresChanged(_) {
+  void _measuresChanged(List<ListChangeRecord> _) {
     if (_measures is! ObservableList) return;
     notifyChange(new ChartSeriesChangeRecord(this));
   }
diff --git a/packages/charted/lib/charts/src/chart_state_impl.dart b/packages/charted/lib/charts/src/chart_state_impl.dart
index 44f5d74..e5bccd8 100644
--- a/packages/charted/lib/charts/src/chart_state_impl.dart
+++ b/packages/charted/lib/charts/src/chart_state_impl.dart
@@ -26,8 +26,7 @@
   LinkedHashSet<int> hidden = new LinkedHashSet<int>();
 
   LinkedHashSet<int> selection = new LinkedHashSet<int>();
-  LinkedHashSet<Pair<int, int>> highlights =
-      new LinkedHashSet<Pair<int, int>>();
+  LinkedHashSet<Pair<int, int>> highlights = new LinkedHashSet<Pair<int, int>>();
 
   Pair<int, int> _hovered;
   int _preview;
@@ -47,7 +46,6 @@
       _hovered = value;
       notifyChange(new ChartHoverChangeRecord(_hovered));
     }
-    return value;
   }
 
   Pair<int, int> get hovered => _hovered;
@@ -58,7 +56,6 @@
       _preview = value;
       notifyChange(new ChartPreviewChangeRecord(_preview));
     }
-    return value;
   }
 
   int get preview => _preview;
@@ -115,7 +112,7 @@
       if (isSelectOrHighlight) {
         selection.clear();
       }
-      var item = new Pair(column, row);
+      var item = new Pair<int, int>(column, row);
       highlights.add(item);
       notifyChange(new ChartHighlightChangeRecord(add: item));
     }
@@ -124,7 +121,7 @@
 
   bool unhighlight(int column, int row) {
     if (isHighlighted(column, row)) {
-      var item = new Pair(column, row);
+      var item = new Pair<int, int>(column, row);
       highlights.remove(item);
       notifyChange(new ChartHighlightChangeRecord(remove: item));
     }
diff --git a/packages/charted/lib/charts/src/layout_area_impl.dart b/packages/charted/lib/charts/src/layout_area_impl.dart
index d4bbaef..c6cd537 100644
--- a/packages/charted/lib/charts/src/layout_area_impl.dart
+++ b/packages/charted/lib/charts/src/layout_area_impl.dart
@@ -78,7 +78,7 @@
   void dispose() {
     _configEventsDisposer.dispose();
     _dataEventsDisposer.dispose();
-    _config.legend.dispose();
+    _config.legend?.dispose();
   }
 
   static bool isNotInline(Element e) =>
@@ -205,45 +205,45 @@
 
     // If we previously displayed a series, verify that we are
     // still using the same renderer.  Otherwise, dispose the older one.
-    if (_renderer != null && series.renderer != _renderer) {
-      _rendererDisposer.dispose();
-    }
+    if (_renderer != series.renderer) {
+      if (_renderer != null) _rendererDisposer.dispose();
 
-    // Save and subscribe to events on the the current renderer.
-    _renderer = series.renderer;
-    if (_renderer is ChartRendererBehaviorSource) {
-      _rendererDisposer.addAll([
-        _renderer.onValueClick.listen((ChartEvent e) {
-          if (state != null) {
-            if (state.isSelected(e.row)) {
-              state.unselect(e.row);
-            } else {
-              state.select(e.row);
+      // Save and subscribe to events on the the current renderer.
+      _renderer = series.renderer;
+      if (_renderer is ChartRendererBehaviorSource) {
+        _rendererDisposer.addAll([
+          _renderer.onValueClick.listen((ChartEvent e) {
+            if (state != null) {
+              if (state.isSelected(e.row)) {
+                state.unselect(e.row);
+              } else {
+                state.select(e.row);
+              }
             }
-          }
-          if (_valueMouseClickController != null) {
-            _valueMouseClickController.add(e);
-          }
-        }),
-        _renderer.onValueMouseOver.listen((ChartEvent e) {
-          if (state != null) {
-            state.preview = e.row;
-          }
-          if (_valueMouseOverController != null) {
-            _valueMouseOverController.add(e);
-          }
-        }),
-        _renderer.onValueMouseOut.listen((ChartEvent e) {
-          if (state != null) {
-            if (e.row == state.preview) {
-              state.hovered = null;
+            if (_valueMouseClickController != null) {
+              _valueMouseClickController.add(e);
             }
-          }
-          if (_valueMouseOutController != null) {
-            _valueMouseOutController.add(e);
-          }
-        })
-      ]);
+          }),
+          _renderer.onValueMouseOver.listen((ChartEvent e) {
+            if (state != null) {
+              state.preview = e.row;
+            }
+            if (_valueMouseOverController != null) {
+              _valueMouseOverController.add(e);
+            }
+          }),
+          _renderer.onValueMouseOut.listen((ChartEvent e) {
+            if (state != null) {
+              if (e.row == state.preview) {
+                state.hovered = null;
+              }
+            }
+            if (_valueMouseOutController != null) {
+              _valueMouseOutController.add(e);
+            }
+          })
+        ]);
+      }
     }
 
     Iterable<ChartLegendItem> legend =
diff --git a/packages/charted/lib/core/interpolators/easing.dart b/packages/charted/lib/core/interpolators/easing.dart
index e80bbd6..1cf833d 100644
--- a/packages/charted/lib/core/interpolators/easing.dart
+++ b/packages/charted/lib/core/interpolators/easing.dart
@@ -32,46 +32,6 @@
 /// altered [EasingFunction].
 typedef EasingFunction EasingModeFunction(EasingFunction fn);
 
-/// Creates an easing function based on type and mode.
-EasingFunction easingFunctionByName(String type,
-    [String mode = EASE_MODE_IN, List params]) {
-  const Map easingTypes = const {
-    EASE_TYPE_LINEAR: identityFunction,
-    EASE_TYPE_POLY: easePoly,
-    EASE_TYPE_QUAD: easeQuad,
-    EASE_TYPE_CUBIC: easeCubic,
-    EASE_TYPE_SIN: easeSin,
-    EASE_TYPE_EXP: easeExp,
-    EASE_TYPE_CIRCLE: easeCircle,
-    EASE_TYPE_ELASTIC: easeElastic,
-    EASE_TYPE_BACK: easeBack,
-    EASE_TYPE_BOUNCE: easeBounce
-  };
-
-  const Map easingModes = const {
-    EASE_MODE_IN: identityFunction,
-    EASE_MODE_OUT: reverseEasingFn,
-    EASE_MODE_IN_OUT: reflectEasingFn,
-    EASE_MODE_OUT_IN: reflectReverseEasingFn
-  };
-
-  const Map customEasingFunctions = const {
-    '$EASE_TYPE_CUBIC-$EASE_MODE_IN_OUT': easeCubicInOut
-  };
-
-  assert(easingTypes.containsKey(type));
-  assert(easingModes.containsKey(mode));
-
-  EasingFunction fn;
-  if (customEasingFunctions.containsKey('$type-$mode')) {
-    fn = Function.apply(customEasingFunctions['$type-$mode'], params);
-  } else {
-    fn = Function.apply(easingTypes[type], params);
-    fn = easingModes[mode](fn);
-  }
-  return clampEasingFn(fn);
-}
-
 /// Clamps transition progress to stay between 0.0 and 1.0
 EasingFunction clampEasingFn(EasingFunction f) =>
     (t) => t <= 0 ? 0 : t >= 1 ? 1 : f(t);
diff --git a/packages/charted/lib/core/interpolators/interpolators.dart b/packages/charted/lib/core/interpolators/interpolators.dart
index 56dc9df..7be1f24 100644
--- a/packages/charted/lib/core/interpolators/interpolators.dart
+++ b/packages/charted/lib/core/interpolators/interpolators.dart
@@ -25,7 +25,8 @@
 /// more interpolators are added, one of the internal implementations are
 /// selected by the type of [a] and [b].
 Interpolator createInterpolatorFromRegistry(a, b) {
-  var fn, i = _interpolators.length;
+  Interpolator fn;
+  int i = _interpolators.length;
   while (--i >= 0 && fn == null) {
     fn = _interpolators[i](a, b);
   }
@@ -37,17 +38,21 @@
 /// Usage note: Use this method only when type of [a] and [b] are not known.
 ///     When used, this function will prevent tree shaking of all built-in
 ///     interpolators.
-Interpolator createInterpolatorByType(a, b) => (a is List && b is List)
-    ? createListInterpolator(a, b)
-    : (a is Map && b is Map)
-        ? createMapInterpolator(a, b)
-        : (a is String && b is String)
-            ? createStringInterpolator(a, b)
-            : (a is num && b is num)
-                ? createNumberInterpolator(a, b)
-                : (a is Color && b is Color)
-                    ? createRgbColorInterpolator(a, b)
-                    : (t) => (t <= 0.5) ? a : b;
+Interpolator createInterpolatorByType(a, b) {
+  if (a is List && b is List) {
+    return createListInterpolator(a, b);
+  } else if (a is Map && b is Map) {
+    return createMapInterpolator(a, b);
+  } else if (a is String && b is String) {
+    return createStringInterpolator(a, b);
+  } else if (a is num && b is num) {
+    return createNumberInterpolator(a, b);
+  } else if (a is Color && b is Color) {
+    return createRgbColorInterpolator(a, b);
+  } else {
+    return (t) => (t <= 0.5) ? a : b;
+  }
+}
 
 //
 // Implementations of InterpolatorGenerator
diff --git a/packages/charted/lib/core/scales.dart b/packages/charted/lib/core/scales.dart
index e4a9948..48a11f5 100644
--- a/packages/charted/lib/core/scales.dart
+++ b/packages/charted/lib/core/scales.dart
@@ -113,8 +113,9 @@
   factory RoundingFunctions.defaults() =>
       new RoundingFunctions((x) => x.floor(), (x) => x.ceil());
 
-  factory RoundingFunctions.identity() =>
-      new RoundingFunctions(identityFunction, identityFunction);
+  factory RoundingFunctions.identity() => new RoundingFunctions(
+      (num n) => identityFunction/*<num>*/(n),
+      (num n) => identityFunction/*<num>*/(n));
 
   RoundFunction get floor => super.first;
   RoundFunction get ceil => super.last;
diff --git a/packages/charted/lib/core/scales/linear_scale.dart b/packages/charted/lib/core/scales/linear_scale.dart
index 4c983dc..ae745cc 100644
--- a/packages/charted/lib/core/scales/linear_scale.dart
+++ b/packages/charted/lib/core/scales/linear_scale.dart
@@ -45,8 +45,12 @@
         : ScaleUtils.bilinearScale;
 
     Function uninterpolator = clamp ? uninterpolateClamp : uninterpolateNumber;
-    InterpolatorGenerator interpolator =
-        _rounded ? createRoundedNumberInterpolator : createNumberInterpolator;
+    InterpolatorGenerator interpolator;
+    if (rounded) {
+      interpolator = createRoundedNumberInterpolator;
+    } else {
+      interpolator = createNumberInterpolator;
+    }
 
     _invert = linear(_range, _domain, uninterpolator, createNumberInterpolator);
     _scale = linear(_domain, _range, uninterpolator, interpolator);
@@ -126,10 +130,10 @@
   Extent get rangeExtent => ScaleUtils.extent(_range);
 
   @override
-  num scale(num value) => _scale(value);
+  scale(value) => _scale(value);
 
   @override
-  num invert(num value) => _invert(value);
+  invert(value) => _invert(value);
 
   Range _linearTickRange([Extent extent]) {
     if (extent == null) {
diff --git a/packages/charted/lib/core/scales/ordinal_scale.dart b/packages/charted/lib/core/scales/ordinal_scale.dart
index 718966a..695f951 100644
--- a/packages/charted/lib/core/scales/ordinal_scale.dart
+++ b/packages/charted/lib/core/scales/ordinal_scale.dart
@@ -39,7 +39,7 @@
   }
 
   @override
-  dynamic invert(num value) {
+  dynamic invert(value) {
     int position = _range.indexOf(value);
     return position > -1 && position < _domain.length
         ? _domain[position]
@@ -94,7 +94,8 @@
   num get rangeBand => _rangeBand;
 
   @override
-  FormatFunction createTickFormatter([String format]) => identityFunction;
+  FormatFunction createTickFormatter([String format]) =>
+      (String s) => identityFunction/*<String>*/(s);
 
   @override
   Iterable get ticks => _domain;
@@ -153,8 +154,9 @@
     scale._reset = (_OrdinalScale s) {
       var start = range.first,
           stop = range.last,
-          step = ((stop - start) /
-              (s.domain.length - padding + 2 * outerPadding)).floor(),
+          step =
+          ((stop - start) / (s.domain.length - padding + 2 * outerPadding))
+              .floor(),
           error = stop - start - (s.domain.length - padding) * step;
 
       s._range = s._steps(start + (error / 2).round(), step);
diff --git a/packages/charted/lib/core/scales/time_scale.dart b/packages/charted/lib/core/scales/time_scale.dart
index d1b439b..37a4b64 100644
--- a/packages/charted/lib/core/scales/time_scale.dart
+++ b/packages/charted/lib/core/scales/time_scale.dart
@@ -67,7 +67,7 @@
   TimeScale._clone(TimeScale source) : super._clone(source);
 
   @override
-  scale(dynamic val) =>
+  scale(Object val) =>
       super.scale(val is DateTime ? val.millisecondsSinceEpoch : val);
 
   @override
@@ -116,13 +116,15 @@
     if (skip > 1) {
       domain = ScaleUtils.nice(
           domain,
-          new RoundingFunctions((date) {
+          new RoundingFunctions((dateMillis) {
+            var date = new DateTime.fromMillisecondsSinceEpoch(dateMillis);
             while (skipped(date = (interval as TimeInterval).floor(date))) {
               date = new DateTime.fromMillisecondsSinceEpoch(
                   date.millisecondsSinceEpoch - 1);
             }
             return date.millisecondsSinceEpoch;
-          }, (date) {
+          }, (dateMillis) {
+            var date = new DateTime.fromMillisecondsSinceEpoch(dateMillis);
             while (skipped(date = (interval as TimeInterval).ceil(date))) {
               date = new DateTime.fromMillisecondsSinceEpoch(
                   date.millisecondsSinceEpoch + 1);
@@ -173,13 +175,13 @@
   DateTime ceil(dynamic val) => _toDateTime(val);
   DateTime round(dynamic val) => _toDateTime(val);
 
-  DateTime offset(dynamic val, num dt) {
+  DateTime offset(Object val, num dt) {
     assert(val is int || val is DateTime);
     return new DateTime.fromMillisecondsSinceEpoch(
         val is int ? val + dt : (val as DateTime).millisecondsSinceEpoch + dt);
   }
 
-  List range(var t0, var t1, int step) {
+  List<DateTime> range(var t0, var t1, int step) {
     int start = t0 is DateTime ? t0.millisecondsSinceEpoch : t0,
         stop = t1 is DateTime ? t1.millisecondsSinceEpoch : t1;
     return new Range((start / step).ceil() * step, stop, step)
diff --git a/packages/charted/lib/core/text_metrics/segmentation.dart b/packages/charted/lib/core/text_metrics/segmentation.dart
index 058ac38..997099a 100644
--- a/packages/charted/lib/core/text_metrics/segmentation.dart
+++ b/packages/charted/lib/core/text_metrics/segmentation.dart
@@ -185,7 +185,7 @@
   return CODE_CATEGORY_OTHER; // Defaults to OTHER.
 }
 
-Iterable<int> graphemeBreakIndices(String s) {
+List<int> graphemeBreakIndices(String s) {
   List<int> indices = [];
   int previousType = 0;
   for (var iter = s.runes.iterator; iter.moveNext();) {
diff --git a/packages/charted/lib/core/timer.dart b/packages/charted/lib/core/timer.dart
index 93856dd..0e3c640 100644
--- a/packages/charted/lib/core/timer.dart
+++ b/packages/charted/lib/core/timer.dart
@@ -16,7 +16,7 @@
 
 typedef bool TimerCallback(int time);
 
-class AnimationTimer extends LinkedListEntry {
+class AnimationTimer extends LinkedListEntry<AnimationTimer> {
   static LinkedList<AnimationTimer> _queue = new LinkedList<AnimationTimer>();
 
   /// true if we are already waiting for window.animationFrame. At any given
@@ -78,7 +78,7 @@
   }
 
   /// Internal timer and animation frame handler.
-  _step([_]) {
+  _step([num _]) {
     int delay = flush();
 
     if (delay == null) {
diff --git a/packages/charted/lib/core/utils.dart b/packages/charted/lib/core/utils.dart
index abbdb1b..37f3e46 100644
--- a/packages/charted/lib/core/utils.dart
+++ b/packages/charted/lib/core/utils.dart
@@ -32,7 +32,7 @@
 const String ORIENTATION_BOTTOM = 'bottom';
 
 /// Identity function that returns the value passed as it's parameter.
-identityFunction(x) => x;
+/*=T*/ identityFunction/*<T>*/(/*=T*/x) => x;
 
 /// Function that formats a value to String.
 typedef String FormatFunction(value);
diff --git a/packages/charted/lib/core/utils/color.dart b/packages/charted/lib/core/utils/color.dart
index 5912a5e..5f80759 100644
--- a/packages/charted/lib/core/utils/color.dart
+++ b/packages/charted/lib/core/utils/color.dart
@@ -276,8 +276,8 @@
 
     hex = hex.substring(1);
     if (hex.length == 3) {
-      for (final char in hex) {
-        final val = int.parse(char, radix: 16);
+      for (int i = 0; i < hex.length; i++) {
+        final val = int.parse(hex[i], radix: 16);
         rgb = (rgb * 16 + val) * 16 + val;
       }
     } else if (hex.length == 6) {
diff --git a/packages/charted/lib/core/utils/lists.dart b/packages/charted/lib/core/utils/lists.dart
index 3a5b05c..02689a9 100644
--- a/packages/charted/lib/core/utils/lists.dart
+++ b/packages/charted/lib/core/utils/lists.dart
@@ -99,7 +99,7 @@
     return new Range._internal(start, stop, step, values);
   }
 
-  Range._internal(this.start, this.stop, this.step, List values)
+  Range._internal(this.start, this.stop, this.step, List<num> values)
       : super(values);
 
   static int _integerConversionFactor(num val) {
diff --git a/packages/charted/lib/core/utils/rect.dart b/packages/charted/lib/core/utils/rect.dart
index 3e666ee..beaa2cc 100644
--- a/packages/charted/lib/core/utils/rect.dart
+++ b/packages/charted/lib/core/utils/rect.dart
@@ -10,18 +10,23 @@
 
 /// Interface representing size and position of an element
 class Rect {
-  final num x;
-  final num y;
-  final num width;
-  final num height;
+  final num _x;
+  final num _y;
+  final num _width;
+  final num _height;
 
-  const Rect([this.x = 0, this.y = 0, this.width = 0, this.height = 0]);
-  const Rect.size(this.width, this.height)
-      : x = 0,
-        y = 0;
-  const Rect.position(this.x, this.y)
-      : width = 0,
-        height = 0;
+  num get x => _x;
+  num get y => _y;
+  num get width => _width;
+  num get height => _height;
+
+  const Rect([this._x = 0, this._y = 0, this._width = 0, this._height = 0]);
+  const Rect.size(this._width, this._height)
+      : _x = 0,
+        _y = 0;
+  const Rect.position(this._x, this._y)
+      : _width = 0,
+        _height = 0;
 
   bool isSameSizeAs(Rect other) =>
       other != null && width == other.width && height == other.height;
diff --git a/packages/charted/lib/layout/src/hierarchy_layout.dart b/packages/charted/lib/layout/src/hierarchy_layout.dart
index 9997ab0..f4da426 100644
--- a/packages/charted/lib/layout/src/hierarchy_layout.dart
+++ b/packages/charted/lib/layout/src/hierarchy_layout.dart
@@ -28,7 +28,7 @@
   /// first element its children in depth first order.
   List<T> layout(
       List rows, int parentColumn, int labelColumn, int valueColumn) {
-    List<HierarchyNode> nodeList = [];
+    List<T> nodeList = [];
     for (var row in rows) {
       nodeList.add(createNode(row[labelColumn], row[valueColumn], 0));
     }
@@ -38,9 +38,7 @@
       if (parentRow == ROOT_ROW_INDEX) continue;
       var currentNode = nodeList[i];
       var parentNode = nodeList[parentRow];
-      (parentNode.children.isEmpty)
-          ? parentNode.children = [currentNode]
-          : parentNode.children.add(currentNode);
+      parentNode.children.add(currentNode);
       currentNode.parent = parentNode;
       currentNode.depth = parentNode.depth + 1;
       for (var child in currentNode.children) {
@@ -50,9 +48,9 @@
 
     // Reorder the list so that root is the first element and the list contains
     // the hierarchy of nodes in depth first order.
-    var hierarchyNodeList = [];
+    var hierarchyNodeList = <HierarchyNode>[];
     var root = nodeList.where((e) => e.depth == 0).elementAt(0);
-    var children = [root];
+    var children = <HierarchyNode>[root];
     while (children.length > 0) {
       var node = children.removeLast();
       children.addAll(node.children);
@@ -80,7 +78,7 @@
   HierarchyNode parent = null;
 
   /// The list of children nodes, or null for leaf nodes.
-  List children = [];
+  List<HierarchyNode> get children;
 
   /// The label to show for each block of hierarchy
   String label = '';
diff --git a/packages/charted/lib/layout/src/pie_layout.dart b/packages/charted/lib/layout/src/pie_layout.dart
index bb316af..88fb85a 100644
--- a/packages/charted/lib/layout/src/pie_layout.dart
+++ b/packages/charted/lib/layout/src/pie_layout.dart
@@ -67,10 +67,14 @@
   }
 
   /** Sets a constant value to start angle of the layout */
-  set startAngle(num value) => startAngleCallback = toCallback(value);
+  set startAngle(num value) {
+    startAngleCallback = toCallback(value);
+  }
 
   /** Sets a constant value to end angle of the layout */
-  set endAngle(num value) => endAngleCallback = toCallback(value);
+  set endAngle(num value) {
+    endAngleCallback = toCallback(value);
+  }
 
   /** Default value accessor */
   static num defaultValueAccessor(num d, i) => d;
diff --git a/packages/charted/lib/layout/src/treemap_layout.dart b/packages/charted/lib/layout/src/treemap_layout.dart
index 601d0d4..39e82a5 100644
--- a/packages/charted/lib/layout/src/treemap_layout.dart
+++ b/packages/charted/lib/layout/src/treemap_layout.dart
@@ -15,7 +15,7 @@
  * Utility layout class which recursively subdivides area into rectangles which
  * can be used to quickly visualize the size of any node in the tree.
  */
-class TreeMapLayout extends HierarchyLayout {
+class TreeMapLayout extends HierarchyLayout<TreeMapNode> {
   /// Rectangular subdivision; squareness controlled via the target ratio.
   static const TREEMAP_LAYOUT_SQUARIFY = 0;
 
@@ -163,7 +163,7 @@
       var rect = _treeMapPad(node, paddingFunction(node));
       List<TreeMapNode> nodes = [];
       var area = 0;
-      var remaining = new List.from(children);
+      var remaining = new List<TreeMapNode>.from(children);
       var score,
           n,
           best = double.INFINITY,
@@ -203,6 +203,8 @@
 }
 
 class TreeMapNode extends HierarchyNode {
+  final List<TreeMapNode> children = <TreeMapNode>[];
+
   /// The minimum x-coordinate of the node position.
   num x = 0;
 
diff --git a/packages/charted/lib/locale/format/number_format.dart b/packages/charted/lib/locale/format/number_format.dart
index 5761e2b..9e938f9 100644
--- a/packages/charted/lib/locale/format/number_format.dart
+++ b/packages/charted/lib/locale/format/number_format.dart
@@ -186,13 +186,13 @@
         before = formatGroup(before);
       }
 
-      var length = prefix.length +
-              before.length +
-              after.length +
-              (zcomma ? 0 : negative.length),
-          padding = length < width
-              ? new List.filled((length = width - length + 1), '').join(fill)
-              : '';
+      int length = prefix.length +
+          before.length +
+          after.length +
+          (zcomma ? 0 : negative.length);
+      var padding = length < width
+          ? new List.filled((length = width - length + 1), '').join(fill)
+          : '';
 
       // If the fill character is '0', grouping is applied after padding.
       if (zcomma) {
diff --git a/packages/charted/lib/locale/format/time_format.dart b/packages/charted/lib/locale/format/time_format.dart
index d1b0e6b..89ab88c 100644
--- a/packages/charted/lib/locale/format/time_format.dart
+++ b/packages/charted/lib/locale/format/time_format.dart
@@ -44,7 +44,7 @@
     while (++i < n) formats[i][0] = _getInstance(formats[i][0] as String);
     return (var date) {
       if (date is num) {
-        date = new DateTime.fromMillisecondsSinceEpoch(date.toInt());
+        date = new DateTime.fromMillisecondsSinceEpoch((date as num).toInt());
       }
       var i = 0, f = formats[i];
       while (f.length < 2 || f[1](date) == false) {
diff --git a/packages/charted/lib/selection/selection.dart b/packages/charted/lib/selection/selection.dart
index c9036dc..8615b46 100644
--- a/packages/charted/lib/selection/selection.dart
+++ b/packages/charted/lib/selection/selection.dart
@@ -10,7 +10,7 @@
  */
 library charted.selection;
 
-import "dart:html" show Element, Event, document;
+import "dart:html" show Element, Event, EventListener, document;
 import "dart:math" as math;
 import "package:charted/core/utils.dart";
 import "package:charted/selection/transition.dart";
@@ -37,7 +37,7 @@
 typedef E SelectionValueAccessor<E>(datum, int index);
 
 /** Create a ChartedCallback that always returns [val] */
-SelectionCallback toCallback(val) => (datum, index, element) => val;
+SelectionCallback/*<T>*/ toCallback/*<T>*/(/*=T*/ val) => (datum, index, element) => val;
 
 /** Create a ChartedValueAccessor that always returns [val] */
 SelectionValueAccessor toValueAccessor(val) => (datum, index) => val;
@@ -57,7 +57,7 @@
    * Collection of groups - A selection when created by calling [selectAll]
    * on an existing [Selection], could contain more than one group.
    */
-  Iterable<SelectionGroup> groups;
+  List<SelectionGroup> groups;
 
   /**
    * Scope of this selection that manages the element, data associations for
@@ -292,7 +292,7 @@
  * Each selection may contain more than one group of elements.
  */
 abstract class SelectionGroup {
-  Iterable<Element> elements;
+  List<Element> elements;
   Element parent;
 }
 
diff --git a/packages/charted/lib/selection/selection_scope.dart b/packages/charted/lib/selection/selection_scope.dart
index 38d43f2..03c2d39 100644
--- a/packages/charted/lib/selection/selection_scope.dart
+++ b/packages/charted/lib/selection/selection_scope.dart
@@ -11,7 +11,7 @@
 /** SelectionScope represents a scope for all the data and DOM operations. */
 class SelectionScope {
   Expando _associations = new Expando();
-  Expando<Map<String, Pair<Function, bool>>> _listeners = new Expando();
+  Expando<Map<String, Pair<EventListener, bool>>> _listeners = new Expando();
   Element _root;
 
   /** Creates a new selection scope with document as the root. */
@@ -57,7 +57,7 @@
   datum(Object element) => element == null ? null : _associations[element];
 
   /** Associates data to the given [element]. */
-  associate(Object element, datum) =>
+  associate(Element element, datum) =>
       datum != null ? _associations[element] = datum : null;
 
   /**
diff --git a/packages/charted/lib/selection/src/selection_impl.dart b/packages/charted/lib/selection/src/selection_impl.dart
index 14de177..5e84a69 100644
--- a/packages/charted/lib/selection/src/selection_impl.dart
+++ b/packages/charted/lib/selection/src/selection_impl.dart
@@ -13,7 +13,7 @@
  * the select or selectAll methods on [SelectionScope] and [Selection].
  */
 class _SelectionImpl implements Selection {
-  Iterable<SelectionGroup> groups;
+  List<SelectionGroup> groups;
   SelectionScope scope;
 
   /**
@@ -112,15 +112,16 @@
   }
 
   /** Creates a selection using the pre-computed list of [SelectionGroup] */
-  _SelectionImpl.selectionGroups(
-      Iterable<SelectionGroup> this.groups, SelectionScope this.scope);
+  _SelectionImpl.selectionGroups(this.groups, this.scope);
 
   /**
    * Creates a selection using the list of elements. All elements will
    * be part of the same group, with [SelectionScope.root] as the group's parent
    */
-  _SelectionImpl.elements(Iterable elements, SelectionScope this.scope) {
-    groups = new List<SelectionGroup>()..add(new _SelectionGroupImpl(elements));
+  _SelectionImpl.elements(
+      Iterable<Element> elements, SelectionScope this.scope) {
+    groups = new List<SelectionGroup>()
+      ..add(new _SelectionGroupImpl(elements.toList()));
   }
 
   /**
@@ -145,7 +146,7 @@
   }
 
   void on(String type, [SelectionCallback listener, bool capture]) {
-    Function getEventHandler(i, e) => (Event event) {
+    EventListener getEventHandler(i, e) => (Event event) {
           var previous = scope.event;
           scope.event = event;
           try {
@@ -178,7 +179,7 @@
       // Remove all listeners on the event type (ignoring the namespace)
       each((d, i, Element e) {
         var handlers = scope._listeners[e], t = type.substring(1);
-        handlers.forEach((String s, Pair<Function, bool> value) {
+        handlers.forEach((String s, Pair<EventListener, bool> value) {
           if (s.split('.')[0] == t) {
             e.removeEventListener(s, value.first, value.last);
           }
@@ -281,10 +282,12 @@
 
   Selection appendWithCallback(SelectionCallback<Element> fn) {
     assert(fn != null);
-    return new _SelectionImpl.single(fn: (datum, ei, e) {
-      Element child = fn(datum, ei, e);
-      return child == null ? null : e.append(child);
-    }, source: this);
+    return new _SelectionImpl.single(
+        fn: (datum, ei, e) {
+          Element child = fn(datum, ei, e);
+          return child == null ? null : e.append(child);
+        },
+        source: this);
   }
 
   Selection insert(String tag,
@@ -301,11 +304,13 @@
     assert(fn != null);
     beforeFn =
         before == null ? beforeFn : (d, ei, e) => e.querySelector(before);
-    return new _SelectionImpl.single(fn: (datum, ei, e) {
-      Element child = fn(datum, ei, e);
-      Element before = beforeFn(datum, ei, e);
-      return child == null ? null : e.insertBefore(child, before);
-    }, source: this);
+    return new _SelectionImpl.single(
+        fn: (datum, ei, e) {
+          Element child = fn(datum, ei, e);
+          Element before = beforeFn(datum, ei, e);
+          return child == null ? null : e.insertBefore(child, before);
+        },
+        source: this);
   }
 
   Selection selectAll(String selector) {
@@ -327,11 +332,13 @@
       [SelectionKeyFunction keyFn]) {
     assert(fn != null);
 
-    var enterGroups = [], updateGroups = [], exitGroups = [];
+    var enterGroups = <SelectionGroup>[],
+        updateGroups = <SelectionGroup>[],
+        exitGroups = <SelectionGroup>[];
 
     // Create a dummy node to be used with enter() selection.
-    Object dummy(val) {
-      var element = new Object();
+    Element dummy(val) {
+      var element = new Element.div();
       scope.associate(element, val);
       return element;
     }
@@ -345,9 +352,9 @@
       // Nodes exiting, entering and updating in this group.
       // We maintain the nodes at the same index as they currently
       // are (for exiting) or where they should be (for entering and updating)
-      var update = new List(valuesLength),
-          enter = new List(valuesLength),
-          exit = new List(elementsLength);
+      var update = new List<Element>(valuesLength);
+      var enter = new List<Element>(valuesLength);
+      var exit = new List<Element>(elementsLength);
 
       // Use key function to determine DOMElement to data associations.
       if (keyFn != null) {
@@ -449,7 +456,10 @@
   EnterSelection enter;
   ExitSelection exit;
 
-  _DataSelectionImpl(Iterable updated, Iterable entering, Iterable exiting,
+  _DataSelectionImpl(
+      List<SelectionGroup> updated,
+      Iterable<SelectionGroup> entering,
+      Iterable<SelectionGroup> exiting,
       SelectionScope scope)
       : super.selectionGroups(updated, scope) {
     enter = new _EnterSelectionImpl(entering, this);
@@ -464,7 +474,7 @@
   SelectionScope scope;
   Iterable<SelectionGroup> groups;
 
-  _EnterSelectionImpl(Iterable this.groups, DataSelection this.update) {
+  _EnterSelectionImpl(this.groups, this.update) {
     scope = update.scope;
   }
 
@@ -510,11 +520,11 @@
   }
 
   Selection selectWithCallback(SelectionCallback<Element> fn) {
-    var subgroups = [];
+    var subgroups = <SelectionGroup>[];
     for (int gi = 0, len = groups.length; gi < len; ++gi) {
       final g = groups.elementAt(gi);
       final u = update.groups.elementAt(gi);
-      final subgroup = [];
+      final subgroup = <Element>[];
       for (int ei = 0, eLen = g.elements.length; ei < eLen; ++ei) {
         final e = g.elements.elementAt(ei);
         if (e != null) {
@@ -535,13 +545,13 @@
 /* Implementation of [ExitSelection] */
 class _ExitSelectionImpl extends _SelectionImpl implements ExitSelection {
   final DataSelection update;
-  _ExitSelectionImpl(Iterable groups, DataSelection update)
+  _ExitSelectionImpl(List<SelectionGroup> groups, DataSelection update)
       : update = update,
         super.selectionGroups(groups, update.scope);
 }
 
 class _SelectionGroupImpl implements SelectionGroup {
-  Iterable<Element> elements;
+  List<Element> elements;
   Element parent;
   _SelectionGroupImpl(this.elements, {this.parent});
 }
diff --git a/packages/charted/lib/selection/src/transition_impl.dart b/packages/charted/lib/selection/src/transition_impl.dart
index 204f28c..ff6ff7a 100644
--- a/packages/charted/lib/selection/src/transition_impl.dart
+++ b/packages/charted/lib/selection/src/transition_impl.dart
@@ -13,15 +13,15 @@
 
 class _TransitionImpl implements Transition {
   SelectionCallback _delay = (d, i, c) => 0;
-  SelectionCallback _duration = (d, i, c) =>
-      Transition.defaultDurationMilliseconds;
+  SelectionCallback _duration =
+      (d, i, c) => Transition.defaultDurationMilliseconds;
   Selection _selection;
   Map _attrs = {};
   Map _styles = {};
   Map _attrTweens = {};
   Map _styleTweens = {};
   Map<AnimationTimer, Element> _timerMap = {};
-  Map<Element, List<Map>> _attrMap = {};
+  Map<Element, List<Interpolator>> _attrMap = {};
   Map<Element, int> _durationMap = {};
   bool _interrupted = false;
   bool _remove = false;
@@ -82,7 +82,7 @@
   _transitionNode(num delay) {
     new AnimationTimer((elapsed) {
       _selection.each((d, i, c) {
-        var tweenList = [];
+        var tweenList = <Interpolator>[];
         _attrs.forEach((key, value) {
           tweenList.add(_getAttrInterpolator(c, key, value(d, i, c)));
         });
@@ -117,14 +117,16 @@
   }
 
   // Returns the correct interpolator function for the old and new attribute.
-  _getAttrInterpolator(Element element, String attrName, newValue) {
+  Interpolator _getAttrInterpolator(
+      Element element, String attrName, newValue) {
     var attr = element.attributes[attrName];
     var interpolator = createStringInterpolator(attr, newValue.toString());
     return (t) => element.setAttribute(attrName, interpolator(t).toString());
   }
 
   // Returns the correct interpolator function for the old and new style.
-  _getStyleInterpolator(Element element, String styleName, newValue, priority) {
+  Interpolator _getStyleInterpolator(
+      Element element, String styleName, newValue, priority) {
     var style = element.style.getPropertyValue(styleName);
 
     var interpolator = createStringInterpolator(style, newValue.toString());
@@ -136,7 +138,7 @@
   // Ticks of the transition, this is the callback registered to the
   // ChartedTimer, called on each animation frame until the transition duration
   // has been reached.
-  bool _tick(elapsed) {
+  bool _tick(int elapsed) {
     if (_interrupted) {
       return true;
     }
diff --git a/packages/charted/lib/selection/transition.dart b/packages/charted/lib/selection/transition.dart
index 0f54c0c..43846a3 100644
--- a/packages/charted/lib/selection/transition.dart
+++ b/packages/charted/lib/selection/transition.dart
@@ -7,7 +7,7 @@
  */
 library charted.selection.transition;
 
-import "dart:html" show Element, document;
+import "dart:html" show Element;
 import "package:charted/core/timer.dart";
 import "package:charted/selection/selection.dart";
 import "package:charted/core/interpolators.dart";
diff --git a/packages/charted/lib/svg/shapes/line.dart b/packages/charted/lib/svg/shapes/line.dart
index 7e0f6ac..6633652 100644
--- a/packages/charted/lib/svg/shapes/line.dart
+++ b/packages/charted/lib/svg/shapes/line.dart
@@ -18,7 +18,9 @@
 class SvgLine implements SvgShape {
   static const LINE_INTERPOLATOR_LINEAR = 'linear';
 
-  static final LINE_INTERPOLATORS = {LINE_INTERPOLATOR_LINEAR: _linear};
+  static final LINE_INTERPOLATORS = <String, LineInterpolator>{
+    LINE_INTERPOLATOR_LINEAR: _linear
+  };
 
   /// Callback to access/convert datum to x coordinate value.
   final SelectionValueAccessor<num> xValueAccessor;
@@ -51,7 +53,7 @@
   @override
   String path(data, int index, Element e) {
     assert(data is Iterable);
-    var segments = new StringBuffer(), points = [];
+    var segments = new StringBuffer(), points = <math.Point<num>>[];
     for (int i = 0, len = data.length; i < len; ++i) {
       final d = data.elementAt(i);
       if (isDefined(d, i, e)) {
@@ -80,6 +82,6 @@
   static bool defaultIsDefined(d, i, e) => d != null;
 
   /// Linear interpolator.
-  static String _linear(Iterable points, _) =>
+  static String _linear(Iterable points, int _) =>
       points.map((pt) => '${pt.x},${pt.y}').join('L');
 }
diff --git a/packages/charted/pubspec.yaml b/packages/charted/pubspec.yaml
index 5dc5abc..cb9707a 100644
--- a/packages/charted/pubspec.yaml
+++ b/packages/charted/pubspec.yaml
@@ -1,5 +1,5 @@
 name: charted
-version: 0.3.0
+version: 0.4.0+1
 authors:
 - Prasad Sunkari <prsd@google.com>
 - Michael Cheng <midoringo@google.com>
diff --git a/packages/charted/tool/build_unicode_segmentation_data.dart b/packages/charted/tool/build_unicode_segmentation_data.dart
index 4ec1d47..00e29a5 100644
--- a/packages/charted/tool/build_unicode_segmentation_data.dart
+++ b/packages/charted/tool/build_unicode_segmentation_data.dart
@@ -53,7 +53,7 @@
   buffer.write(HEADER);
   buffer.writeln('const CODE_POINT_BLOCKS = const[');
 
-  List<Iterable> items = [];
+  List<List> items = [];
   data.split('\n').forEach((String line) {
     Match match = lineRegExp.matchAsPrefix(line);
     if (match == null) return;
diff --git a/pubspec.yaml b/pubspec.yaml
index f40c309..3f53ff7 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -14,7 +14,7 @@
     commandLineOptions: [--show-package-warnings]
 dependencies:
   args: any
-  charted: ^0.3.0
+  charted: ^0.4.0
   polymer: ^0.16.3
   unittest: < 0.12.0
   js: ^0.6.0