You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@echarts.apache.org by sh...@apache.org on 2020/02/27 15:10:20 UTC

[incubator-echarts] branch typescript updated: ts: add types for dataZoom model

This is an automated email from the ASF dual-hosted git repository.

shenyi pushed a commit to branch typescript
in repository https://gitbox.apache.org/repos/asf/incubator-echarts.git


The following commit(s) were added to refs/heads/typescript by this push:
     new db01fc7  ts: add types for dataZoom model
db01fc7 is described below

commit db01fc75ff91f7099b93a4bfd9a345cc4613cd7d
Author: pissang <bm...@gmail.com>
AuthorDate: Thu Feb 27 23:04:01 2020 +0800

    ts: add types for dataZoom model
---
 src/chart/bar/barItemStyle.ts                      |  17 +-
 src/chart/funnel/FunnelView.ts                     |   1 -
 src/chart/gauge/GaugeView.ts                       |   2 +-
 src/component/dataZoom/AxisProxy.ts                | 328 +++++++--------
 src/component/dataZoom/DataZoomModel.ts            | 467 +++++++++++----------
 src/component/dataZoom/InsideZoomModel.ts          |  51 ++-
 src/component/dataZoom/SliderZoomModel.ts          | 105 ++++-
 src/component/dataZoom/SliderZoomView.ts           |   2 +-
 src/component/dataZoom/dataZoomAction.ts           |  23 +-
 src/component/dataZoom/dataZoomProcessor.ts        |  14 +-
 src/component/dataZoom/helper.ts                   | 101 +++--
 src/component/dataZoom/typeDefaulter.ts            |   2 -
 src/component/legend/LegendView.ts                 |  10 +-
 src/component/toolbox/feature/Brush.ts             |   2 +-
 src/component/toolbox/feature/MagicType.ts         |   2 +-
 .../typeDefaulter.ts => coord/AxisBaseModel.ts}    |  20 +-
 src/coord/axisCommonTypes.ts                       |   3 +-
 src/coord/axisHelper.ts                            |   2 +-
 src/coord/axisModelCreator.ts                      |   9 +-
 src/coord/cartesian/Axis2D.ts                      |   4 +-
 src/coord/cartesian/AxisModel.ts                   |  20 +-
 src/coord/cartesian/Grid.ts                        |  10 +-
 src/coord/cartesian/cartesianAxisHelper.ts         |   4 +-
 src/coord/polar/AxisModel.ts                       |  10 +-
 src/coord/polar/Polar.ts                           |  13 +-
 src/coord/single/AxisModel.ts                      |  10 +-
 src/coord/single/Single.ts                         |  13 +-
 src/data/List.ts                                   |  22 +-
 src/model/mixin/areaStyle.ts                       |   7 +-
 src/model/mixin/itemStyle.ts                       |  10 +-
 src/model/mixin/lineStyle.ts                       |   9 +-
 src/util/model.ts                                  |  10 +-
 src/util/types.ts                                  |  22 +
 33 files changed, 761 insertions(+), 564 deletions(-)

diff --git a/src/chart/bar/barItemStyle.ts b/src/chart/bar/barItemStyle.ts
index 7bbd247..7776ac6 100644
--- a/src/chart/bar/barItemStyle.ts
+++ b/src/chart/bar/barItemStyle.ts
@@ -17,9 +17,9 @@
 * under the License.
 */
 
-// @ts-nocheck
-
 import makeStyleMapper from '../../model/mixin/makeStyleMapper';
+import { StyleProps } from 'zrender/src/graphic/Style';
+import Model from '../../model/Model';
 
 var getBarItemStyle = makeStyleMapper(
     [
@@ -37,8 +37,19 @@ var getBarItemStyle = makeStyleMapper(
     ]
 );
 
+type BarItemStyleKeys = 'fill'
+    | 'stroke'
+    | 'lineWidth'
+    | 'stroke'
+    | 'lineWidth'
+    | 'opacity'
+    | 'shadowBlur'
+    | 'shadowOffsetX'
+    | 'shadowOffsetY'
+    | 'shadowColor'
+type ItemStyleProps = Pick<StyleProps, BarItemStyleKeys>
 export default {
-    getBarItemStyle: function (excludes) {
+    getBarItemStyle: function (this: Model, excludes?: BarItemStyleKeys[]): ItemStyleProps {
         var style = getBarItemStyle(this, excludes);
         if (this.getBorderLineDash) {
             var lineDash = this.getBorderLineDash();
diff --git a/src/chart/funnel/FunnelView.ts b/src/chart/funnel/FunnelView.ts
index d942e4a..6802860 100644
--- a/src/chart/funnel/FunnelView.ts
+++ b/src/chart/funnel/FunnelView.ts
@@ -20,7 +20,6 @@
 import * as graphic from '../../util/graphic';
 import * as zrUtil from 'zrender/src/core/util';
 import ChartView from '../../view/Chart';
-import ComponentView from '../../view/Component';
 import FunnelSeriesModel from './FunnelSeries';
 import GlobalModel from '../../model/Global';
 import ExtensionAPI from '../../ExtensionAPI';
diff --git a/src/chart/gauge/GaugeView.ts b/src/chart/gauge/GaugeView.ts
index 56cf113..c9beb0c 100644
--- a/src/chart/gauge/GaugeView.ts
+++ b/src/chart/gauge/GaugeView.ts
@@ -131,7 +131,7 @@ class GaugeView extends ChartView {
             sector.setStyle(lineStyleModel.getLineStyle(
                 // Because we use sector to simulate arc
                 // so the properties for stroking are useless
-                ['color', 'borderWidth', 'borderColor']
+                ['color', 'width']
             ));
 
             group.add(sector);
diff --git a/src/component/dataZoom/AxisProxy.ts b/src/component/dataZoom/AxisProxy.ts
index 87dbaa0..78e81b8 100644
--- a/src/component/dataZoom/AxisProxy.ts
+++ b/src/component/dataZoom/AxisProxy.ts
@@ -17,118 +17,94 @@
 * under the License.
 */
 
-// @ts-nocheck
-
 import * as zrUtil from 'zrender/src/core/util';
 import * as numberUtil from '../../util/number';
 import * as helper from './helper';
 import sliderMove from '../helper/sliderMove';
+import GlobalModel from '../../model/Global';
+import SeriesModel from '../../model/Series';
+import ExtensionAPI from '../../ExtensionAPI';
+import { Dictionary } from '../../util/types';
+// TODO Polar?
+import CartesianAxisModel from '../../coord/cartesian/AxisModel';
+import DataZoomModel from './DataZoomModel';
+import { AxisBaseModel } from '../../coord/AxisBaseModel';
 
 var each = zrUtil.each;
 var asc = numberUtil.asc;
 
+interface MinMaxSpan {
+    minSpan: number
+    maxSpan: number
+    minValueSpan: number
+    maxValueSpan: number
+}
+
+type SupportedAxis = 'xAxis' | 'yAxis' | 'angleAxis' | 'radiusAxis' | 'singleAxis'
+
 /**
  * Operate single axis.
  * One axis can only operated by one axis operator.
  * Different dataZoomModels may be defined to operate the same axis.
  * (i.e. 'inside' data zoom and 'slider' data zoom components)
  * So dataZoomModels share one axisProxy in that case.
- *
- * @class
  */
-var AxisProxy = function (dimName, axisIndex, dataZoomModel, ecModel) {
+class AxisProxy {
 
-    /**
-     * @private
-     * @type {string}
-     */
-    this._dimName = dimName;
+    ecModel: GlobalModel
 
-    /**
-     * @private
-     */
-    this._axisIndex = axisIndex;
 
-    /**
-     * @private
-     * @type {Array.<number>}
-     */
-    this._valueWindow;
+    private _dimName: string
+    private _axisIndex: number
 
-    /**
-     * @private
-     * @type {Array.<number>}
-     */
-    this._percentWindow;
+    private _valueWindow: [number, number]
+    private _percentWindow: [number, number]
 
-    /**
-     * @private
-     * @type {Array.<number>}
-     */
-    this._dataExtent;
+    private _dataExtent: [number, number]
 
-    /**
-     * {minSpan, maxSpan, minValueSpan, maxValueSpan}
-     * @private
-     * @type {Object}
-     */
-    this._minMaxSpan;
+    private _minMaxSpan: MinMaxSpan
 
-    /**
-     * @readOnly
-     * @type {module: echarts/model/Global}
-     */
-    this.ecModel = ecModel;
+    private _dataZoomModel: DataZoomModel
 
-    /**
-     * @private
-     * @type {module: echarts/component/dataZoom/DataZoomModel}
-     */
-    this._dataZoomModel = dataZoomModel;
+    constructor(dimName: string, axisIndex: number, dataZoomModel: DataZoomModel, ecModel: GlobalModel) {
+        this._dimName = dimName;
 
-    // /**
-    //  * @readOnly
-    //  * @private
-    //  */
-    // this.hasSeriesStacked;
-};
+        this._axisIndex = axisIndex;
 
-AxisProxy.prototype = {
+        this.ecModel = ecModel;
 
-    constructor: AxisProxy,
+        this._dataZoomModel = dataZoomModel;
+
+        // /**
+        //  * @readOnly
+        //  * @private
+        //  */
+        // this.hasSeriesStacked;
+    }
 
     /**
      * Whether the axisProxy is hosted by dataZoomModel.
-     *
-     * @public
-     * @param {module: echarts/component/dataZoom/DataZoomModel} dataZoomModel
-     * @return {boolean}
      */
-    hostedBy: function (dataZoomModel) {
+    hostedBy(dataZoomModel: DataZoomModel): boolean {
         return this._dataZoomModel === dataZoomModel;
-    },
+    }
 
     /**
-     * @return {Array.<number>} Value can only be NaN or finite value.
+     * @return Value can only be NaN or finite value.
      */
-    getDataValueWindow: function () {
-        return this._valueWindow.slice();
-    },
+    getDataValueWindow() {
+        return this._valueWindow.slice() as [number, number];
+    }
 
     /**
      * @return {Array.<number>}
      */
-    getDataPercentWindow: function () {
-        return this._percentWindow.slice();
-    },
+    getDataPercentWindow() {
+        return this._percentWindow.slice() as [number, number];
+    }
 
-    /**
-     * @public
-     * @param {number} axisIndex
-     * @return {Array} seriesModels
-     */
-    getTargetSeriesModels: function () {
-        var seriesModels = [];
+    getTargetSeriesModels() {
+        var seriesModels: SeriesModel[] = [];
         var ecModel = this.ecModel;
 
         ecModel.eachSeries(function (seriesModel) {
@@ -136,8 +112,8 @@ AxisProxy.prototype = {
                 var dimName = this._dimName;
                 var axisModel = ecModel.queryComponents({
                     mainType: dimName + 'Axis',
-                    index: seriesModel.get(dimName + 'AxisIndex'),
-                    id: seriesModel.get(dimName + 'AxisId')
+                    index: seriesModel.get(dimName + 'AxisIndex' as any),
+                    id: seriesModel.get(dimName + 'AxisId' as any)
                 })[0];
                 if (this._axisIndex === (axisModel && axisModel.componentIndex)) {
                     seriesModels.push(seriesModel);
@@ -146,19 +122,19 @@ AxisProxy.prototype = {
         }, this);
 
         return seriesModels;
-    },
+    }
 
-    getAxisModel: function () {
-        return this.ecModel.getComponent(this._dimName + 'Axis', this._axisIndex);
-    },
+    getAxisModel(): AxisBaseModel {
+        return this.ecModel.getComponent(this._dimName + 'Axis', this._axisIndex) as AxisBaseModel;
+    }
 
-    getOtherAxisModel: function () {
+    getOtherAxisModel() {
         var axisDim = this._dimName;
         var ecModel = this.ecModel;
         var axisModel = this.getAxisModel();
         var isCartesian = axisDim === 'x' || axisDim === 'y';
-        var otherAxisDim;
-        var coordSysIndexName;
+        var otherAxisDim: 'x' | 'y' | 'radius' | 'angle';
+        var coordSysIndexName: 'gridIndex' | 'polarIndex';
         if (isCartesian) {
             coordSysIndexName = 'gridIndex';
             otherAxisDim = axisDim === 'x' ? 'y' : 'x';
@@ -169,41 +145,40 @@ AxisProxy.prototype = {
         }
         var foundOtherAxisModel;
         ecModel.eachComponent(otherAxisDim + 'Axis', function (otherAxisModel) {
-            if ((otherAxisModel.get(coordSysIndexName) || 0)
-                === (axisModel.get(coordSysIndexName) || 0)
+            if (((otherAxisModel as CartesianAxisModel).get(coordSysIndexName as 'gridIndex') || 0)
+                === ((axisModel as CartesianAxisModel).get(coordSysIndexName as 'gridIndex') || 0)
             ) {
                 foundOtherAxisModel = otherAxisModel;
             }
         });
         return foundOtherAxisModel;
-    },
+    }
 
-    getMinMaxSpan: function () {
+    getMinMaxSpan() {
         return zrUtil.clone(this._minMaxSpan);
-    },
+    }
 
     /**
      * Only calculate by given range and this._dataExtent, do not change anything.
-     *
-     * @param {Object} opt
-     * @param {number} [opt.start]
-     * @param {number} [opt.end]
-     * @param {number} [opt.startValue]
-     * @param {number} [opt.endValue]
      */
-    calculateDataWindow: function (opt) {
+    calculateDataWindow(opt?: {
+        start?: number
+        end?: number
+        startValue?: number
+        endValue?: number
+    }) {
         var dataExtent = this._dataExtent;
         var axisModel = this.getAxisModel();
         var scale = axisModel.axis.scale;
         var rangePropMode = this._dataZoomModel.getRangePropMode();
         var percentExtent = [0, 100];
-        var percentWindow = [];
-        var valueWindow = [];
+        var percentWindow = [] as unknown as [number, number];
+        var valueWindow = [] as unknown as [number, number];
         var hasPropModeValue;
 
-        each(['start', 'end'], function (prop, idx) {
+        each(['start', 'end'] as const, function (prop, idx) {
             var boundPercent = opt[prop];
-            var boundValue = opt[prop + 'Value'];
+            var boundValue = opt[prop + 'Value' as 'startValue' | 'endValue'];
 
             // Notice: dataZoom is based either on `percentProp` ('start', 'end') or
             // on `valueProp` ('startValue', 'endValue'). (They are based on the data extent
@@ -256,9 +231,19 @@ AxisProxy.prototype = {
             ? restrictSet(valueWindow, percentWindow, dataExtent, percentExtent, false)
             : restrictSet(percentWindow, valueWindow, percentExtent, dataExtent, true);
 
-        function restrictSet(fromWindow, toWindow, fromExtent, toExtent, toValue) {
+        function restrictSet(
+            fromWindow: number[],
+            toWindow: number[],
+            fromExtent: number[],
+            toExtent: number[],
+            toValue: boolean
+        ) {
             var suffix = toValue ? 'Span' : 'ValueSpan';
-            sliderMove(0, fromWindow, fromExtent, 'all', spans['min' + suffix], spans['max' + suffix]);
+            sliderMove(
+                0, fromWindow, fromExtent, 'all',
+                spans['min' + suffix as 'minSpan' | 'minValueSpan'],
+                spans['max' + suffix as 'maxSpan' | 'maxValueSpan']
+            );
             for (var i = 0; i < 2; i++) {
                 toWindow[i] = numberUtil.linearMap(fromWindow[i], fromExtent, toExtent, true);
                 toValue && (toWindow[i] = scale.parse(toWindow[i]));
@@ -269,16 +254,14 @@ AxisProxy.prototype = {
             valueWindow: valueWindow,
             percentWindow: percentWindow
         };
-    },
+    }
 
     /**
      * Notice: reset should not be called before series.restoreData() called,
      * so it is recommanded to be called in "process stage" but not "model init
      * stage".
-     *
-     * @param {module: echarts/component/dataZoom/DataZoomModel} dataZoomModel
      */
-    reset: function (dataZoomModel) {
+    reset(dataZoomModel: DataZoomModel) {
         if (dataZoomModel !== this._dataZoomModel) {
             return;
         }
@@ -298,7 +281,7 @@ AxisProxy.prototype = {
         // }, this);
 
         // `calculateDataWindow` uses min/maxSpan.
-        setMinMaxSpan(this);
+        this._updateMinMaxSpan();
 
         var dataWindow = this.calculateDataWindow(dataZoomModel.settledOption);
 
@@ -306,25 +289,19 @@ AxisProxy.prototype = {
         this._percentWindow = dataWindow.percentWindow;
 
         // Update axis setting then.
-        setAxisModel(this);
-    },
+        this._setAxisModel();
+    }
 
-    /**
-     * @param {module: echarts/component/dataZoom/DataZoomModel} dataZoomModel
-     */
-    restore: function (dataZoomModel) {
+    restore(dataZoomModel: DataZoomModel) {
         if (dataZoomModel !== this._dataZoomModel) {
             return;
         }
 
         this._valueWindow = this._percentWindow = null;
-        setAxisModel(this, true);
-    },
+        this._setAxisModel(true);
+    }
 
-    /**
-     * @param {module: echarts/component/dataZoom/DataZoomModel} dataZoomModel
-     */
-    filterData: function (dataZoomModel, api) {
+    filterData(dataZoomModel: DataZoomModel, api: ExtensionAPI) {
         if (dataZoomModel !== this._dataZoomModel) {
             return;
         }
@@ -373,7 +350,7 @@ AxisProxy.prototype = {
                     var rightOut;
                     var hasValue;
                     for (var i = 0; i < dataDims.length; i++) {
-                        var value = seriesData.get(dataDims[i], dataIndex);
+                        var value = seriesData.get(dataDims[i], dataIndex) as number;
                         var thisHasValue = !isNaN(value);
                         var thisLeftOut = value < valueWindow[0];
                         var thisRightOut = value > valueWindow[1];
@@ -392,13 +369,13 @@ AxisProxy.prototype = {
                 each(dataDims, function (dim) {
                     if (filterMode === 'empty') {
                         seriesModel.setData(
-                            seriesData = seriesData.map(dim, function (value) {
+                            seriesData = seriesData.map(dim, function (value: number) {
                                 return !isInWindow(value) ? NaN : value;
                             })
                         );
                     }
                     else {
-                        var range = {};
+                        var range: Dictionary<[number, number]> = {};
                         range[dim] = valueWindow;
 
                         // console.time('select');
@@ -413,13 +390,63 @@ AxisProxy.prototype = {
             });
         });
 
-        function isInWindow(value) {
+        function isInWindow(value: number) {
             return value >= valueWindow[0] && value <= valueWindow[1];
         }
     }
-};
 
-function calculateDataExtent(axisProxy, axisDim, seriesModels) {
+    private _updateMinMaxSpan() {
+        var minMaxSpan = this._minMaxSpan = {} as MinMaxSpan;
+        var dataZoomModel = this._dataZoomModel;
+        var dataExtent = this._dataExtent;
+
+        each(['min', 'max'], function (minMax) {
+            var percentSpan = dataZoomModel.get(minMax + 'Span' as 'minSpan' | 'maxSpan');
+            var valueSpan = dataZoomModel.get(minMax + 'ValueSpan' as 'minValueSpan' | 'maxValueSpan');
+            valueSpan != null && (valueSpan = this.getAxisModel().axis.scale.parse(valueSpan));
+
+            // minValueSpan and maxValueSpan has higher priority than minSpan and maxSpan
+            if (valueSpan != null) {
+                percentSpan = numberUtil.linearMap(
+                    dataExtent[0] + valueSpan, dataExtent, [0, 100], true
+                );
+            }
+            else if (percentSpan != null) {
+                valueSpan = numberUtil.linearMap(
+                    percentSpan, [0, 100], dataExtent, true
+                ) - dataExtent[0];
+            }
+
+            minMaxSpan[minMax + 'Span' as 'minSpan' | 'maxSpan'] = percentSpan;
+            minMaxSpan[minMax + 'ValueSpan' as 'minValueSpan' | 'maxValueSpan'] = valueSpan;
+        }, this);
+    }
+
+    private _setAxisModel(isRestore?: boolean) {
+
+        var axisModel = this.getAxisModel();
+
+        var percentWindow = this._percentWindow;
+        var valueWindow = this._valueWindow;
+
+        if (!percentWindow) {
+            return;
+        }
+
+        // [0, 500]: arbitrary value, guess axis extent.
+        var precision = numberUtil.getPixelPrecision(valueWindow, [0, 500]);
+        precision = Math.min(precision, 20);
+        // isRestore or isFull
+        var useOrigin = isRestore || (percentWindow[0] === 0 && percentWindow[1] === 100);
+
+        axisModel.setRange(
+            useOrigin ? null : +valueWindow[0].toFixed(precision),
+            useOrigin ? null : +valueWindow[1].toFixed(precision)
+        );
+    }
+}
+
+function calculateDataExtent(axisProxy: AxisProxy, axisDim: string, seriesModels: SeriesModel[]) {
     var dataExtent = [Infinity, -Infinity];
 
     each(seriesModels, function (seriesModel) {
@@ -448,11 +475,11 @@ function calculateDataExtent(axisProxy, axisDim, seriesModels) {
     // consistent.
     fixExtentByAxis(axisProxy, dataExtent);
 
-    return dataExtent;
+    return dataExtent as [number, number];
 }
 
-function fixExtentByAxis(axisProxy, dataExtent) {
-    var axisModel = axisProxy.getAxisModel();
+function fixExtentByAxis(axisProxy: AxisProxy, dataExtent: number[]) {
+    var axisModel = axisProxy.getAxisModel() as CartesianAxisModel;
     var min = axisModel.getMin(true);
 
     // For category axis, if min/max/scale are not set, extent is determined
@@ -488,53 +515,4 @@ function fixExtentByAxis(axisProxy, dataExtent) {
     return dataExtent;
 }
 
-function setAxisModel(axisProxy, isRestore) {
-    var axisModel = axisProxy.getAxisModel();
-
-    var percentWindow = axisProxy._percentWindow;
-    var valueWindow = axisProxy._valueWindow;
-
-    if (!percentWindow) {
-        return;
-    }
-
-    // [0, 500]: arbitrary value, guess axis extent.
-    var precision = numberUtil.getPixelPrecision(valueWindow, [0, 500]);
-    precision = Math.min(precision, 20);
-    // isRestore or isFull
-    var useOrigin = isRestore || (percentWindow[0] === 0 && percentWindow[1] === 100);
-
-    axisModel.setRange(
-        useOrigin ? null : +valueWindow[0].toFixed(precision),
-        useOrigin ? null : +valueWindow[1].toFixed(precision)
-    );
-}
-
-function setMinMaxSpan(axisProxy) {
-    var minMaxSpan = axisProxy._minMaxSpan = {};
-    var dataZoomModel = axisProxy._dataZoomModel;
-    var dataExtent = axisProxy._dataExtent;
-
-    each(['min', 'max'], function (minMax) {
-        var percentSpan = dataZoomModel.get(minMax + 'Span');
-        var valueSpan = dataZoomModel.get(minMax + 'ValueSpan');
-        valueSpan != null && (valueSpan = axisProxy.getAxisModel().axis.scale.parse(valueSpan));
-
-        // minValueSpan and maxValueSpan has higher priority than minSpan and maxSpan
-        if (valueSpan != null) {
-            percentSpan = numberUtil.linearMap(
-                dataExtent[0] + valueSpan, dataExtent, [0, 100], true
-            );
-        }
-        else if (percentSpan != null) {
-            valueSpan = numberUtil.linearMap(
-                percentSpan, [0, 100], dataExtent, true
-            ) - dataExtent[0];
-        }
-
-        minMaxSpan[minMax + 'Span'] = percentSpan;
-        minMaxSpan[minMax + 'ValueSpan'] = valueSpan;
-    });
-}
-
 export default AxisProxy;
diff --git a/src/component/dataZoom/DataZoomModel.ts b/src/component/dataZoom/DataZoomModel.ts
index 8414c50..a1b7e4c 100644
--- a/src/component/dataZoom/DataZoomModel.ts
+++ b/src/component/dataZoom/DataZoomModel.ts
@@ -17,119 +17,183 @@
 * under the License.
 */
 
-// @ts-nocheck
-
 import {__DEV__} from '../../config';
-import * as echarts from '../../echarts';
 import * as zrUtil from 'zrender/src/core/util';
 import env from 'zrender/src/core/env';
 import * as modelUtil from '../../util/model';
 import * as helper from './helper';
 import AxisProxy from './AxisProxy';
+import ComponentModel from '../../model/Component';
+import {
+    LayoutOrient,
+    ComponentOption,
+    Dictionary,
+    LabelOption,
+    SeriesOption,
+    SeriesOnCartesianOptionMixin,
+    SeriesOnPolarOptionMixin,
+    SeriesOnSingleOptionMixin
+} from '../../util/types';
+import Model from '../../model/Model';
+import GlobalModel from '../../model/Global';
+import SeriesModel from '../../model/Series';
+import { AxisBaseModel } from '../../coord/AxisBaseModel';
+import { OptionAxisType, AxisBaseOption } from '../../coord/axisCommonTypes';
 
 var each = zrUtil.each;
 var eachAxisDim = helper.eachAxisDim;
 
-var DataZoomModel = echarts.extendComponentModel({
+export interface DataZoomOption extends ComponentOption {
 
-    type: 'dataZoom',
+    /**
+     * Default auto by axisIndex
+     */
+    orient?: LayoutOrient
 
-    dependencies: [
-        'xAxis', 'yAxis', 'zAxis', 'radiusAxis', 'angleAxis', 'singleAxis', 'series'
-    ],
+    /**
+     * Default the first horizontal category axis.
+     */
+    xAxisIndex?: number | number[]
 
     /**
-     * @protected
+     * Default the first vertical category axis.
+     */
+    yAxisIndex?: number | number[]
+
+    radiusAxisIndex?: number | number[]
+    angleAxisIndex?: number | number[]
+
+    singleAxisIndex?: number | number[]
+
+    /**
+     * Possible values: 'filter' or 'empty' or 'weakFilter'.
+     * 'filter': data items which are out of window will be removed. This option is
+     *         applicable when filtering outliers. For each data item, it will be
+     *         filtered if one of the relevant dimensions is out of the window.
+     * 'weakFilter': data items which are out of window will be removed. This option
+     *         is applicable when filtering outliers. For each data item, it will be
+     *         filtered only if all  of the relevant dimensions are out of the same
+     *         side of the window.
+     * 'empty': data items which are out of window will be set to empty.
+     *         This option is applicable when user should not neglect
+     *         that there are some data items out of window.
+     * 'none': Do not filter.
+     * Taking line chart as an example, line will be broken in
+     * the filtered points when filterModel is set to 'empty', but
+     * be connected when set to 'filter'.
+     */
+    filterMode?: 'filter' | 'weakFilter' | 'empty' | 'none'
+
+    /**
+     * Dispatch action by the fixed rate, avoid frequency.
+     * default 100. Do not throttle when use null/undefined.
+     * If animation === true and animationDurationUpdate > 0,
+     * default value is 100, otherwise 20.
      */
-    defaultOption: {
+    throttle?: number | null | undefined
+    /**
+     * Start percent. 0 ~ 100
+     */
+    start?: number
+    /**
+     * End percent. 0 ~ 100
+     */
+    end?: number
+    /**
+     * Start value. If startValue specified, start is ignored
+     */
+    startValue?: number
+    /**
+     * End value. If endValue specified, end is ignored.
+     */
+    endValue?: number
+    /**
+     * Min span percent, 0 - 100
+     * The range of dataZoom can not be smaller than that.
+     */
+    minSpan?: number
+    /**
+     * Max span percent, 0 - 100
+     * The range of dataZoom can not be larger than that.
+     */
+    maxSpan?: number
+
+    minValueSpan?: number
+
+    maxValueSpan?: number
+
+    rangeMode?: ['value' | 'percent', 'value' | 'percent']
+
+    realtime?: boolean
+
+    // Available when type is slider
+    textStyle?: LabelOption
+}
+
+type RangeOption = Pick<DataZoomOption, 'start' | 'end' | 'startValue' | 'endValue'>
+
+type ExtendedAxisBaseModel = AxisBaseModel & {
+    __dzAxisProxy: AxisProxy
+}
+
+interface SeriesModelOnAxis extends SeriesModel<
+    SeriesOption & SeriesOnCartesianOptionMixin & SeriesOnPolarOptionMixin & SeriesOnSingleOptionMixin
+> {}
+
+class DataZoomModel<Opts extends DataZoomOption = DataZoomOption> extends ComponentModel<Opts> {
+    static type = 'dataZoom'
+    type = DataZoomModel.type
+
+    static dependencies = [
+        'xAxis', 'yAxis', 'zAxis', 'radiusAxis', 'angleAxis', 'singleAxis', 'series'
+    ]
+
+
+    static defaultOption: DataZoomOption = {
         zlevel: 0,
         z: 4,                   // Higher than normal component (z: 2).
-        orient: null,           // Default auto by axisIndex. Possible value: 'horizontal', 'vertical'.
-        xAxisIndex: null,       // Default the first horizontal category axis.
-        yAxisIndex: null,       // Default the first vertical category axis.
-
-        filterMode: 'filter',   // Possible values: 'filter' or 'empty' or 'weakFilter'.
-                                // 'filter': data items which are out of window will be removed. This option is
-                                //          applicable when filtering outliers. For each data item, it will be
-                                //          filtered if one of the relevant dimensions is out of the window.
-                                // 'weakFilter': data items which are out of window will be removed. This option
-                                //          is applicable when filtering outliers. For each data item, it will be
-                                //          filtered only if all  of the relevant dimensions are out of the same
-                                //          side of the window.
-                                // 'empty': data items which are out of window will be set to empty.
-                                //          This option is applicable when user should not neglect
-                                //          that there are some data items out of window.
-                                // 'none': Do not filter.
-                                // Taking line chart as an example, line will be broken in
-                                // the filtered points when filterModel is set to 'empty', but
-                                // be connected when set to 'filter'.
-
-        throttle: null,         // Dispatch action by the fixed rate, avoid frequency.
-                                // default 100. Do not throttle when use null/undefined.
-                                // If animation === true and animationDurationUpdate > 0,
-                                // default value is 100, otherwise 20.
-        start: 0,               // Start percent. 0 ~ 100
-        end: 100,               // End percent. 0 ~ 100
-        startValue: null,       // Start value. If startValue specified, start is ignored.
-        endValue: null,         // End value. If endValue specified, end is ignored.
-        minSpan: null,          // 0 ~ 100
-        maxSpan: null,          // 0 ~ 100
-        minValueSpan: null,     // The range of dataZoom can not be smaller than that.
-        maxValueSpan: null,     // The range of dataZoom can not be larger than that.
-        rangeMode: null         // Array, can be 'value' or 'percent'.
-    },
+
+        filterMode: 'filter',
+
+        start: 0,
+        end: 100
+    }
 
     /**
-     * @override
+     * key like x_0, y_1
      */
-    init: function (option, parentModel, ecModel) {
+    private _dataIntervalByAxis: Dictionary<[number, number]> = {}
 
-        /**
-         * key like x_0, y_1
-         * @private
-         * @type {Object}
-         */
-        this._dataIntervalByAxis = {};
+    private _dataInfo = {}
 
-        /**
-         * @private
-         */
-        this._dataInfo = {};
+    private _axisProxies: Dictionary<AxisProxy> = {}
 
-        /**
-         * key like x_0, y_1
-         * @private
-         */
-        this._axisProxies = {};
+    private _autoThrottle = true
 
-        /**
-         * @readOnly
-         */
-        this.textStyleModel;
+    /**
+     * It is `[rangeModeForMin, rangeModeForMax]`.
+     * The optional values for `rangeMode`:
+     * + `'value'` mode: the axis extent will always be determined by
+     *     `dataZoom.startValue` and `dataZoom.endValue`, despite
+     *     how data like and how `axis.min` and `axis.max` are.
+     * + `'percent'` mode: `100` represents 100% of the `[dMin, dMax]`,
+     *     where `dMin` is `axis.min` if `axis.min` specified, otherwise `data.extent[0]`,
+     *     and `dMax` is `axis.max` if `axis.max` specified, otherwise `data.extent[1]`.
+     *     Axis extent will be determined by the result of the percent of `[dMin, dMax]`.
+     *
+     * For example, when users are using dynamic data (update data periodically via `setOption`),
+     * if in `'value`' mode, the window will be kept in a fixed value range despite how
+     * data are appended, while if in `'percent'` mode, whe window range will be changed alone with
+     * the appended data (suppose `axis.min` and `axis.max` are not specified).
+     */
+    private _rangePropMode: DataZoomOption['rangeMode'] = ['percent', 'percent']
 
-        /**
-         * @private
-         */
-        this._autoThrottle = true;
+    textStyleModel: Model<DataZoomOption['textStyle']>
+
+    settledOption: Opts
+
+    init(option: Opts, parentModel: Model, ecModel: GlobalModel) {
 
-        /**
-         * It is `[rangeModeForMin, rangeModeForMax]`.
-         * The optional values for `rangeMode`:
-         * + `'value'` mode: the axis extent will always be determined by
-         *     `dataZoom.startValue` and `dataZoom.endValue`, despite
-         *     how data like and how `axis.min` and `axis.max` are.
-         * + `'percent'` mode: `100` represents 100% of the `[dMin, dMax]`,
-         *     where `dMin` is `axis.min` if `axis.min` specified, otherwise `data.extent[0]`,
-         *     and `dMax` is `axis.max` if `axis.max` specified, otherwise `data.extent[1]`.
-         *     Axis extent will be determined by the result of the percent of `[dMin, dMax]`.
-         *
-         * For example, when users are using dynamic data (update data periodically via `setOption`),
-         * if in `'value`' mode, the window will be kept in a fixed value range despite how
-         * data are appended, while if in `'percent'` mode, whe window range will be changed alone with
-         * the appended data (suppose `axis.min` and `axis.max` are not specified).
-         *
-         * @private
-         */
         this._rangePropMode = ['percent', 'percent'];
 
         var inputRawOption = retrieveRawOption(option);
@@ -162,12 +226,12 @@ var DataZoomModel = echarts.extendComponentModel({
         this.mergeDefaultAndTheme(option, ecModel);
 
         this.doInit(inputRawOption);
-    },
+    }
 
     /**
      * @override
      */
-    mergeOption: function (newOption) {
+    mergeOption(newOption: Opts) {
         var inputRawOption = retrieveRawOption(newOption);
 
         //FIX #2591
@@ -175,12 +239,12 @@ var DataZoomModel = echarts.extendComponentModel({
         zrUtil.merge(this.settledOption, inputRawOption, true);
 
         this.doInit(inputRawOption);
-    },
+    }
 
     /**
      * @protected
      */
-    doInit: function (inputRawOption) {
+    doInit(inputRawOption: Opts) {
         var thisOption = this.option;
 
         // Disable realtime view update if canvas is not supported.
@@ -190,10 +254,10 @@ var DataZoomModel = echarts.extendComponentModel({
 
         this._setDefaultThrottle(inputRawOption);
 
-        updateRangeUse(this, inputRawOption);
+        this._updateRangeUse(inputRawOption);
 
         var settledOption = this.settledOption;
-        each([['start', 'startValue'], ['end', 'endValue']], function (names, index) {
+        each([['start', 'startValue'], ['end', 'endValue']] as const, function (names, index) {
             // start/end has higher priority over startValue/endValue if they
             // both set, but we should make chart.setOption({endValue: 1000})
             // effective, rather than chart.setOption({endValue: 1000, end: null}).
@@ -208,21 +272,18 @@ var DataZoomModel = echarts.extendComponentModel({
         this._resetTarget();
 
         this._giveAxisProxies();
-    },
+    }
 
-    /**
-     * @private
-     */
-    _giveAxisProxies: function () {
+    private _giveAxisProxies() {
         var axisProxies = this._axisProxies;
 
         this.eachTargetAxis(function (dimNames, axisIndex, dataZoomModel, ecModel) {
             var axisModel = this.dependentModels[dimNames.axis][axisIndex];
 
             // If exists, share axisProxy with other dataZoomModels.
-            var axisProxy = axisModel.__dzAxisProxy || (
+            var axisProxy = (axisModel as ExtendedAxisBaseModel).__dzAxisProxy || (
                 // Use the first dataZoomModel as the main model of axisProxy.
-                axisModel.__dzAxisProxy = new AxisProxy(
+                (axisModel as ExtendedAxisBaseModel).__dzAxisProxy = new AxisProxy(
                     dimNames.name, axisIndex, this, ecModel
                 )
             );
@@ -231,12 +292,9 @@ var DataZoomModel = echarts.extendComponentModel({
 
             axisProxies[dimNames.name + '_' + axisIndex] = axisProxy;
         }, this);
-    },
+    }
 
-    /**
-     * @private
-     */
-    _resetTarget: function () {
+    private _resetTarget() {
         var thisOption = this.option;
 
         var autoMode = this._judgeAutoMode();
@@ -254,12 +312,9 @@ var DataZoomModel = echarts.extendComponentModel({
         else if (autoMode === 'orient') {
             this._autoSetOrient();
         }
-    },
+    }
 
-    /**
-     * @private
-     */
-    _judgeAutoMode: function () {
+    private _judgeAutoMode() {
         // Auto set only works for setOption at the first time.
         // The following is user's reponsibility. So using merged
         // option is OK.
@@ -286,12 +341,9 @@ var DataZoomModel = echarts.extendComponentModel({
             }
             return 'axisIndex';
         }
-    },
+    }
 
-    /**
-     * @private
-     */
-    _autoSetAxisIndex: function () {
+    private _autoSetAxisIndex() {
         var autoAxisIndex = true;
         var orient = this.get('orient', true);
         var thisOption = this.option;
@@ -302,11 +354,13 @@ var DataZoomModel = echarts.extendComponentModel({
             var dimName = orient === 'vertical' ? 'y' : 'x';
 
             if (dependentModels[dimName + 'Axis'].length) {
-                thisOption[dimName + 'AxisIndex'] = [0];
+                thisOption[dimName + 'AxisIndex' as 'xAxisIndex' | 'yAxisIndex'] = [0];
                 autoAxisIndex = false;
             }
             else {
-                each(dependentModels.singleAxis, function (singleAxisModel) {
+                each(dependentModels.singleAxis, function (
+                    singleAxisModel: AxisBaseModel<{'orient': LayoutOrient} & AxisBaseOption>
+                ) {
                     if (autoAxisIndex && singleAxisModel.get('orient', true) === orient) {
                         thisOption.singleAxisIndex = [singleAxisModel.componentIndex];
                         autoAxisIndex = false;
@@ -345,10 +399,10 @@ var DataZoomModel = echarts.extendComponentModel({
             // If both dataZoom.xAxisIndex and dataZoom.yAxisIndex is not specified,
             // dataZoom component auto adopts series that reference to
             // both xAxis and yAxis which type is 'value'.
-            this.ecModel.eachSeries(function (seriesModel) {
+            this.ecModel.eachSeries(function (seriesModel: SeriesModelOnAxis) {
                 if (this._isSeriesHasAllAxesTypeOf(seriesModel, 'value')) {
                     eachAxisDim(function (dimNames) {
-                        var axisIndices = thisOption[dimNames.axisIndex];
+                        var axisIndices = thisOption[dimNames.axisIndex] as number[]; // Has been normalized to array
 
                         var axisIndex = seriesModel.get(dimNames.axisIndex);
                         var axisId = seriesModel.get(dimNames.axisId);
@@ -362,7 +416,7 @@ var DataZoomModel = echarts.extendComponentModel({
                         if (__DEV__) {
                             if (!axisModel) {
                                 throw new Error(
-                                    dimNames.axis + ' "' + zrUtil.retrieve(
+                                    dimNames.axis + ' "' + zrUtil.retrieve<number | string>(
                                         axisIndex,
                                         axisId,
                                         0
@@ -379,13 +433,10 @@ var DataZoomModel = echarts.extendComponentModel({
                 }
             }, this);
         }
-    },
+    }
 
-    /**
-     * @private
-     */
-    _autoSetOrient: function () {
-        var dim;
+    private _autoSetOrient() {
+        var dim: string;
 
         // Find the first axis
         this.eachTargetAxis(function (dimNames) {
@@ -393,12 +444,9 @@ var DataZoomModel = echarts.extendComponentModel({
         }, this);
 
         this.option.orient = dim === 'y' ? 'vertical' : 'horizontal';
-    },
+    }
 
-    /**
-     * @private
-     */
-    _isSeriesHasAllAxesTypeOf: function (seriesModel, axisType) {
+    private _isSeriesHasAllAxesTypeOf(seriesModel: SeriesModelOnAxis, axisType: OptionAxisType) {
         // FIXME
         // 需要series的xAxisIndex和yAxisIndex都首先自动设置上。
         // 例如series.type === scatter时。
@@ -413,12 +461,9 @@ var DataZoomModel = echarts.extendComponentModel({
             }
         }, this);
         return is;
-    },
+    }
 
-    /**
-     * @private
-     */
-    _setDefaultThrottle: function (inputRawOption) {
+    private _setDefaultThrottle(inputRawOption: DataZoomOption) {
         // When first time user set throttle, auto throttle ends.
         if (inputRawOption.hasOwnProperty('throttle')) {
             this._autoThrottle = false;
@@ -429,75 +474,96 @@ var DataZoomModel = echarts.extendComponentModel({
                 globalOption.animation && globalOption.animationDurationUpdate > 0
             ) ? 100 : 20;
         }
-    },
+    }
+
+    private _updateRangeUse(inputRawOption: RangeOption) {
+        var rangePropMode = this._rangePropMode;
+        var rangeModeInOption = this.get('rangeMode');
+
+        each([['start', 'startValue'], ['end', 'endValue']] as const, function (names, index) {
+            var percentSpecified = inputRawOption[names[0]] != null;
+            var valueSpecified = inputRawOption[names[1]] != null;
+            if (percentSpecified && !valueSpecified) {
+                rangePropMode[index] = 'percent';
+            }
+            else if (!percentSpecified && valueSpecified) {
+                rangePropMode[index] = 'value';
+            }
+            else if (rangeModeInOption) {
+                rangePropMode[index] = rangeModeInOption[index];
+            }
+            else if (percentSpecified) { // percentSpecified && valueSpecified
+                rangePropMode[index] = 'percent';
+            }
+            // else remain its original setting.
+        });
+    }
 
     /**
      * @public
      */
-    getFirstTargetAxisModel: function () {
-        var firstAxisModel;
+    getFirstTargetAxisModel() {
+        var firstAxisModel: AxisBaseModel;
         eachAxisDim(function (dimNames) {
             if (firstAxisModel == null) {
-                var indices = this.get(dimNames.axisIndex);
+                var indices = this.get(dimNames.axisIndex) as number[]; // Has been normalized to array
                 if (indices.length) {
-                    firstAxisModel = this.dependentModels[dimNames.axis][indices[0]];
+                    firstAxisModel = this.dependentModels[dimNames.axis][indices[0]] as AxisBaseModel;
                 }
             }
         }, this);
 
         return firstAxisModel;
-    },
+    }
 
     /**
      * @public
      * @param {Function} callback param: axisModel, dimNames, axisIndex, dataZoomModel, ecModel
      */
-    eachTargetAxis: function (callback, context) {
+    eachTargetAxis<Ctx>(
+        callback: (
+            this: Ctx,
+            dimNames: Parameters<Parameters<typeof eachAxisDim>[0]>[0],
+            axisIndex: number,
+            dataZoomModel: this,
+            ecModel: GlobalModel
+        ) => void,
+        context?: Ctx
+    ) {
         var ecModel = this.ecModel;
         eachAxisDim(function (dimNames) {
             each(
-                this.get(dimNames.axisIndex),
+                this.get(dimNames.axisIndex) as number[],   // Has been normalized to array
                 function (axisIndex) {
                     callback.call(context, dimNames, axisIndex, this, ecModel);
                 },
                 this
             );
         }, this);
-    },
+    }
 
     /**
-     * @param {string} dimName
-     * @param {number} axisIndex
-     * @return {module:echarts/component/dataZoom/AxisProxy} If not found, return null/undefined.
+     * @return If not found, return null/undefined.
      */
-    getAxisProxy: function (dimName, axisIndex) {
+    getAxisProxy(dimName: string, axisIndex: number): AxisProxy {
         return this._axisProxies[dimName + '_' + axisIndex];
-    },
+    }
 
     /**
-     * @param {string} dimName
-     * @param {number} axisIndex
-     * @return {module:echarts/model/Model} If not found, return null/undefined.
+     * @return If not found, return null/undefined.
      */
-    getAxisModel: function (dimName, axisIndex) {
+    getAxisModel(dimName: string, axisIndex: number): AxisBaseModel {
         var axisProxy = this.getAxisProxy(dimName, axisIndex);
         return axisProxy && axisProxy.getAxisModel();
-    },
+    }
 
     /**
      * If not specified, set to undefined.
-     *
-     * @public
-     * @param {Object} opt
-     * @param {number} [opt.start]
-     * @param {number} [opt.end]
-     * @param {number} [opt.startValue]
-     * @param {number} [opt.endValue]
      */
-    setRawRange: function (opt) {
+    setRawRange(opt: RangeOption) {
         var thisOption = this.option;
         var settledOption = this.settledOption;
-        each([['start', 'startValue'], ['end', 'endValue']], function (names) {
+        each([['start', 'startValue'], ['end', 'endValue']] as const, function (names) {
             // Consider the pair <start, startValue>:
             // If one has value and the other one is `null/undefined`, we both set them
             // to `settledOption`. This strategy enables the feature to clear the original
@@ -513,44 +579,34 @@ var DataZoomModel = echarts.extendComponentModel({
             }
         }, this);
 
-        updateRangeUse(this, opt);
-    },
+        this._updateRangeUse(opt);
+    }
 
-    /**
-     * @public
-     * @param {Object} opt
-     * @param {number} [opt.start]
-     * @param {number} [opt.end]
-     * @param {number} [opt.startValue]
-     * @param {number} [opt.endValue]
-     */
-    setCalculatedRange: function (opt) {
+    setCalculatedRange(opt: RangeOption) {
         var option = this.option;
-        each(['start', 'startValue', 'end', 'endValue'], function (name) {
+        each(['start', 'startValue', 'end', 'endValue'] as const, function (name) {
             option[name] = opt[name];
         });
-    },
+    }
 
     /**
      * @public
      * @return {Array.<number>} [startPercent, endPercent]
      */
-    getPercentRange: function () {
+    getPercentRange() {
         var axisProxy = this.findRepresentativeAxisProxy();
         if (axisProxy) {
             return axisProxy.getDataPercentWindow();
         }
-    },
+    }
 
     /**
      * @public
      * For example, chart.getModel().getComponent('dataZoom').getValueRange('y', 0);
      *
-     * @param {string} [axisDimName]
-     * @param {number} [axisIndex]
-     * @return {Array.<number>} [startValue, endValue] value can only be '-' or finite number.
+     * @return [startValue, endValue] value can only be '-' or finite number.
      */
-    getValueRange: function (axisDimName, axisIndex) {
+    getValueRange(axisDimName: string, axisIndex: number): [number, number] {
         if (axisDimName == null && axisIndex == null) {
             var axisProxy = this.findRepresentativeAxisProxy();
             if (axisProxy) {
@@ -560,17 +616,16 @@ var DataZoomModel = echarts.extendComponentModel({
         else {
             return this.getAxisProxy(axisDimName, axisIndex).getDataValueWindow();
         }
-    },
+    }
 
     /**
      * @public
-     * @param {module:echarts/model/Model} [axisModel] If axisModel given, find axisProxy
+     * @param axisModel If axisModel given, find axisProxy
      *      corresponding to the axisModel
-     * @return {module:echarts/component/dataZoom/AxisProxy}
      */
-    findRepresentativeAxisProxy: function (axisModel) {
+    findRepresentativeAxisProxy(axisModel?: AxisBaseModel): AxisProxy {
         if (axisModel) {
-            return axisModel.__dzAxisProxy;
+            return (axisModel as ExtendedAxisBaseModel).__dzAxisProxy;
         }
 
         // Find the first hosted axisProxy
@@ -591,26 +646,25 @@ var DataZoomModel = echarts.extendComponentModel({
                 return axisProxies[key];
             }
         }
-    },
+    }
 
     /**
      * @return {Array.<string>}
      */
-    getRangePropMode: function () {
+    getRangePropMode() {
         return this._rangePropMode.slice();
     }
 
-});
-
+}
 /**
  * Retrieve the those raw params from option, which will be cached separately.
  * becasue they will be overwritten by normalized/calculated values in the main
  * process.
  */
-function retrieveRawOption(option) {
-    var ret = {};
+function retrieveRawOption<T extends DataZoomOption>(option: T) {
+    var ret = {} as T;
     each(
-        ['start', 'end', 'startValue', 'endValue', 'throttle'],
+        ['start', 'end', 'startValue', 'endValue', 'throttle'] as const,
         function (name) {
             option.hasOwnProperty(name) && (ret[name] = option[name]);
         }
@@ -618,27 +672,6 @@ function retrieveRawOption(option) {
     return ret;
 }
 
-function updateRangeUse(dataZoomModel, inputRawOption) {
-    var rangePropMode = dataZoomModel._rangePropMode;
-    var rangeModeInOption = dataZoomModel.get('rangeMode');
-
-    each([['start', 'startValue'], ['end', 'endValue']], function (names, index) {
-        var percentSpecified = inputRawOption[names[0]] != null;
-        var valueSpecified = inputRawOption[names[1]] != null;
-        if (percentSpecified && !valueSpecified) {
-            rangePropMode[index] = 'percent';
-        }
-        else if (!percentSpecified && valueSpecified) {
-            rangePropMode[index] = 'value';
-        }
-        else if (rangeModeInOption) {
-            rangePropMode[index] = rangeModeInOption[index];
-        }
-        else if (percentSpecified) { // percentSpecified && valueSpecified
-            rangePropMode[index] = 'percent';
-        }
-        // else remain its original setting.
-    });
-}
+ComponentModel.registerClass(DataZoomModel);
 
 export default DataZoomModel;
\ No newline at end of file
diff --git a/src/component/dataZoom/InsideZoomModel.ts b/src/component/dataZoom/InsideZoomModel.ts
index cdaa18d..2a67dd4 100644
--- a/src/component/dataZoom/InsideZoomModel.ts
+++ b/src/component/dataZoom/InsideZoomModel.ts
@@ -17,23 +17,50 @@
 * under the License.
 */
 
-// @ts-nocheck
+import DataZoomModel, {DataZoomOption} from './DataZoomModel';
+import ComponentModel from '../../model/Component';
 
-import DataZoomModel from './DataZoomModel';
+interface InsideDataZoomOption extends DataZoomOption {
 
-export default DataZoomModel.extend({
+    /**
+     * Whether disable this inside zoom.
+     */
+    disabled?: boolean
+
+    /**
+     * Whether disable zoom but only pan.
+     */
+    zoomLock?: boolean
+
+    zoomOnMouseWheel?: boolean | 'shift' | 'ctrl' | 'alt'
+
+    moveOnMouseMove?: boolean | 'shift' | 'ctrl' | 'alt'
 
-    type: 'dataZoom.inside',
+    moveOnMouseWheel?: boolean | 'shift' | 'ctrl' | 'alt'
+
+    preventDefaultMouseMove?: boolean
 
     /**
-     * @protected
+     * Inside dataZoom don't support textStyle
      */
-    defaultOption: {
-        disabled: false,   // Whether disable this inside zoom.
-        zoomLock: false,   // Whether disable zoom but only pan.
-        zoomOnMouseWheel: true, // Can be: true / false / 'shift' / 'ctrl' / 'alt'.
-        moveOnMouseMove: true,   // Can be: true / false / 'shift' / 'ctrl' / 'alt'.
-        moveOnMouseWheel: false, // Can be: true / false / 'shift' / 'ctrl' / 'alt'.
+    textStyle?: never
+}
+
+
+class InsideZoomModel extends DataZoomModel<InsideDataZoomOption> {
+    static readonly type = 'dataZoom.inside'
+    type = InsideZoomModel.type
+
+    static defaultOption: InsideDataZoomOption = {
+        disabled: false,
+        zoomLock: false,
+        zoomOnMouseWheel: true,
+        moveOnMouseMove: true,
+        moveOnMouseWheel: false,
         preventDefaultMouseMove: true
     }
-});
\ No newline at end of file
+}
+
+ComponentModel.registerClass(InsideZoomModel);
+
+export default InsideZoomModel;
\ No newline at end of file
diff --git a/src/component/dataZoom/SliderZoomModel.ts b/src/component/dataZoom/SliderZoomModel.ts
index 4a102a2..66e4be0 100644
--- a/src/component/dataZoom/SliderZoomModel.ts
+++ b/src/component/dataZoom/SliderZoomModel.ts
@@ -17,35 +17,98 @@
 * under the License.
 */
 
-// @ts-nocheck
+import DataZoomModel, {DataZoomOption} from './DataZoomModel';
+import ComponentModel from '../../model/Component';
+import {
+    BoxLayoutOptionMixin,
+    ZRColor,
+    LineStyleOption,
+    AreaStyleOption,
+    ItemStyleOption,
+    LabelOption
+} from '../../util/types';
 
-import DataZoomModel from './DataZoomModel';
+interface SliderDataZoomOption extends DataZoomOption, BoxLayoutOptionMixin {
 
-var SliderZoomModel = DataZoomModel.extend({
+    show?: boolean
+    /**
+     * Slider dataZoom don't support textStyle
+     */
 
-    type: 'dataZoom.slider',
+    /**
+     * Background of slider zoom component
+     */
+    backgroundColor?: ZRColor
 
-    layoutMode: 'box',
+    /**
+     * @deprecated Use borderColor instead
+     */
+    // dataBackgroundColor?: ZRColor
 
     /**
-     * @protected
+     * border color of the box. For compatibility,
+     * if dataBackgroundColor is set, borderColor
+     * is ignored.
      */
-    defaultOption: {
+    borderColor?: ZRColor
+
+    dataBackground?: {
+        lineStyle?: LineStyleOption
+        areaStyle?: AreaStyleOption
+    }
+
+    /**
+     * Color of selected area.
+     */
+    fillerColor?: ZRColor
+
+    /**
+     * @deprecated Use handleStyle instead
+     */
+    // handleColor?: ZRColor
+
+    handleIcon?: string
+
+    /**
+     * Percent of the slider height
+     */
+    handleSize?: string | number
+
+    handleStyle?: ItemStyleOption
+
+    labelPrecision?: number
+
+    labelFormatter?: string | ((value: number, valueStr: string) => string)
+
+    showDetail?: boolean
+
+    showDataShadow?: 'auto' | boolean
+
+    zoomLock?: boolean
+
+    textStyle?: LabelOption
+}
+
+
+class SliderZoomModel extends DataZoomModel<SliderDataZoomOption> {
+    static readonly type = 'dataZoom.slider'
+    type = SliderZoomModel.type
+
+    static readonly layoutMode = 'box'
+
+    static defaultOption: SliderDataZoomOption = {
         show: true,
 
-        // ph => placeholder. Using placehoder here because
         // deault value can only be drived in view stage.
-        right: 'ph',  // Default align to grid rect.
-        top: 'ph',    // Default align to grid rect.
-        width: 'ph',  // Default align to grid rect.
-        height: 'ph', // Default align to grid rect.
+        right: 'auto',  // Default align to grid rect.
+        top: 'auto',    // Default align to grid rect.
+        width: 'auto',  // Default align to grid rect.
+        height: 'auto', // Default align to grid rect.
         left: null,   // Default align to grid rect.
         bottom: null, // Default align to grid rect.
 
         backgroundColor: 'rgba(47,69,84,0)',    // Background of slider zoom component.
-        // dataBackgroundColor: '#ddd',         // Background coor of data shadow and border of box,
-                                                // highest priority, remain for compatibility of
-                                                // previous version, but not recommended any more.
+        // dataBackgroundColor: '#ddd',
         dataBackground: {
             lineStyle: {
                 color: '#2f4554',
@@ -57,13 +120,10 @@ var SliderZoomModel = DataZoomModel.extend({
                 opacity: 0.3
             }
         },
-        borderColor: '#ddd',                    // border color of the box. For compatibility,
-                                                // if dataBackgroundColor is set, borderColor
-                                                // is ignored.
+        borderColor: '#ddd',
 
         fillerColor: 'rgba(167,183,204,0.4)',     // Color of selected area.
         // handleColor: 'rgba(89,170,216,0.95)',     // Color of handle.
-        // handleIcon: 'path://M4.9,17.8c0-1.4,4.5-10.5,5.5-12.4c0-0.1,0.6-1.1,0.9-1.1c0.4,0,0.9,1,0.9,1.1c1.1,2.2,5.4,11,5.4,12.4v17.8c0,1.5-0.6,2.1-1.3,2.1H6.1c-0.7,0-1.3-0.6-1.3-2.1V17.8z',
         /* eslint-disable */
         handleIcon: 'M8.2,13.6V3.9H6.3v9.7H3.1v14.9h3.3v9.7h1.8v-9.7h3.3V13.6H8.2z M9.7,24.4H4.8v-1.4h4.9V24.4z M9.7,19.1H4.8v-1.4h4.9V19.1z',
         /* eslint-enable */
@@ -74,8 +134,6 @@ var SliderZoomModel = DataZoomModel.extend({
             color: '#a7b7cc'
         },
 
-        labelPrecision: null,
-        labelFormatter: null,
         showDetail: true,
         showDataShadow: 'auto',                 // Default auto decision.
         realtime: true,
@@ -84,7 +142,8 @@ var SliderZoomModel = DataZoomModel.extend({
             color: '#333'
         }
     }
+}
 
-});
+ComponentModel.registerClass(SliderZoomModel);
 
-export default SliderZoomModel;
+export default SliderZoomModel;
\ No newline at end of file
diff --git a/src/component/dataZoom/SliderZoomView.ts b/src/component/dataZoom/SliderZoomView.ts
index 356eb07..432d3be 100644
--- a/src/component/dataZoom/SliderZoomView.ts
+++ b/src/component/dataZoom/SliderZoomView.ts
@@ -211,7 +211,7 @@ var SliderZoomView = DataZoomView.extend({
 
         // Replace the placeholder value.
         zrUtil.each(['right', 'top', 'width', 'height'], function (name) {
-            if (layoutParams[name] === 'ph') {
+            if (layoutParams[name] === 'auto') {
                 layoutParams[name] = positionInfo[name];
             }
         });
diff --git a/src/component/dataZoom/dataZoomAction.ts b/src/component/dataZoom/dataZoomAction.ts
index 52a4108..1385f4a 100644
--- a/src/component/dataZoom/dataZoomAction.ts
+++ b/src/component/dataZoom/dataZoomAction.ts
@@ -17,28 +17,29 @@
 * under the License.
 */
 
-// @ts-nocheck
-
 import * as echarts from '../../echarts';
 import * as zrUtil from 'zrender/src/core/util';
-import * as helper from './helper';
+import GlobalModel from '../../model/Global';
+import { createLinkedNodesFinder, eachAxisDim } from './helper';
+import DataZoomModel from './DataZoomModel';
 
 
-echarts.registerAction('dataZoom', function (payload, ecModel) {
+echarts.registerAction('dataZoom', function (payload, ecModel: GlobalModel) {
 
-    var linkedNodesFinder = helper.createLinkedNodesFinder(
-        zrUtil.bind(ecModel.eachComponent, ecModel, 'dataZoom'),
-        helper.eachAxisDim,
-        function (model, dimNames) {
-            return model.get(dimNames.axisIndex);
+    var linkedNodesFinder = createLinkedNodesFinder(
+        zrUtil.bind(ecModel.eachComponent, ecModel, 'dataZoom' as any),
+        eachAxisDim,
+        function (model: DataZoomModel, dimNames) {
+            // Has been normalized to array
+            return model.get(dimNames.axisIndex) as number[];
         }
     );
 
-    var effectedModels = [];
+    var effectedModels: DataZoomModel[] = [];
 
     ecModel.eachComponent(
         {mainType: 'dataZoom', query: payload},
-        function (model, index) {
+        function (model: DataZoomModel, index: number) {
             effectedModels.push.apply(
                 effectedModels, linkedNodesFinder(model).nodes
             );
diff --git a/src/component/dataZoom/dataZoomProcessor.ts b/src/component/dataZoom/dataZoomProcessor.ts
index c58e8b9..528190c 100644
--- a/src/component/dataZoom/dataZoomProcessor.ts
+++ b/src/component/dataZoom/dataZoomProcessor.ts
@@ -17,10 +17,10 @@
 * under the License.
 */
 
-// @ts-nocheck
-
 import * as echarts from '../../echarts';
 import {createHashMap, each} from 'zrender/src/core/util';
+import SeriesModel from '../../model/Series';
+import DataZoomModel from './DataZoomModel';
 
 echarts.registerProcessor({
 
@@ -28,9 +28,9 @@ echarts.registerProcessor({
     // there is a line series and a pie series, it is better not to update the
     // line series if only pie series is needed to be updated.
     getTargetSeries: function (ecModel) {
-        var seriesModelMap = createHashMap();
+        var seriesModelMap = createHashMap<SeriesModel>();
 
-        ecModel.eachComponent('dataZoom', function (dataZoomModel) {
+        ecModel.eachComponent('dataZoom', function (dataZoomModel: DataZoomModel) {
             dataZoomModel.eachTargetAxis(function (dimNames, axisIndex, dataZoomModel) {
                 var axisProxy = dataZoomModel.getAxisProxy(dimNames.name, axisIndex);
                 each(axisProxy.getTargetSeriesModels(), function (seriesModel) {
@@ -50,12 +50,12 @@ echarts.registerProcessor({
     // execute every frame.
     overallReset: function (ecModel, api) {
 
-        ecModel.eachComponent('dataZoom', function (dataZoomModel) {
+        ecModel.eachComponent('dataZoom', function (dataZoomModel: DataZoomModel) {
             // We calculate window and reset axis here but not in model
             // init stage and not after action dispatch handler, because
             // reset should be called after seriesData.restoreData.
             dataZoomModel.eachTargetAxis(function (dimNames, axisIndex, dataZoomModel) {
-                dataZoomModel.getAxisProxy(dimNames.name, axisIndex).reset(dataZoomModel, api);
+                dataZoomModel.getAxisProxy(dimNames.name, axisIndex).reset(dataZoomModel);
             });
 
             // Caution: data zoom filtering is order sensitive when using
@@ -77,7 +77,7 @@ echarts.registerProcessor({
             });
         });
 
-        ecModel.eachComponent('dataZoom', function (dataZoomModel) {
+        ecModel.eachComponent('dataZoom', function (dataZoomModel: DataZoomModel) {
             // Fullfill all of the range props so that user
             // is able to get them from chart.getOption().
             var axisProxy = dataZoomModel.findRepresentativeAxisProxy();
diff --git a/src/component/dataZoom/helper.ts b/src/component/dataZoom/helper.ts
index e6ac11a..6fd31a3 100644
--- a/src/component/dataZoom/helper.ts
+++ b/src/component/dataZoom/helper.ts
@@ -17,44 +17,52 @@
 * under the License.
 */
 
-// @ts-nocheck
-
 import * as zrUtil from 'zrender/src/core/util';
 import * as formatUtil from '../../util/format';
+import { Dictionary } from '../../util/types';
 
 
-var AXIS_DIMS = ['x', 'y', 'z', 'radius', 'angle', 'single'];
+const AXIS_DIMS = ['x', 'y', 'z', 'radius', 'angle', 'single'] as const;
 // Supported coords.
-var COORDS = ['cartesian2d', 'polar', 'singleAxis'];
+const COORDS = ['cartesian2d', 'polar', 'singleAxis'] as const;
 
-/**
- * @param {string} coordType
- * @return {boolean}
- */
-export function isCoordSupported(coordType) {
+export function isCoordSupported(coordType: string) {
     return zrUtil.indexOf(COORDS, coordType) >= 0;
 }
 
+type AxisAttrMap = {
+    // TODO zAxis ?
+    'axisIndex': 'xAxisIndex' | 'yAxisIndex' | 'radiusAxisIndex' | 'angleAxisIndex' | 'singleAxisIndex'
+    'axis': 'xAxis' | 'yAxis' | 'radiusAxis' | 'angleAxis' | 'singleAxis'
+    'axisId': 'xAxisId' | 'yAxisId' | 'radiusAxisId' | 'angleAxisId' | 'singleAxisId'
+}
 /**
  * Create "each" method to iterate names.
- *
- * @pubilc
- * @param  {Array.<string>} names
- * @param  {Array.<string>=} attrs
- * @return {Function}
  */
-export function createNameEach(names, attrs) {
-    names = names.slice();
-    var capitalNames = zrUtil.map(names, formatUtil.capitalFirst);
-    attrs = (attrs || []).slice();
-    var capitalAttrs = zrUtil.map(attrs, formatUtil.capitalFirst);
-
-    return function (callback, context) {
+function createNameEach<T extends string>(names: readonly T[]) {
+    const attrs = ['axisIndex', 'axis', 'axisId'] as const;
+    const capitalNames = zrUtil.map(names.slice(), formatUtil.capitalFirst);
+    const capitalAttrs = zrUtil.map((attrs || []).slice(), formatUtil.capitalFirst);
+
+    type NameObj = {
+        name: T,
+        capital: string,
+        axisIndex: AxisAttrMap['axisIndex']
+        axis: AxisAttrMap['axis']
+        axisId: AxisAttrMap['axisId']
+    };
+    return function<Ctx> (
+        callback: (this: Ctx, nameObj: NameObj) => void,
+        context?: Ctx
+    ) {
         zrUtil.each(names, function (name, index) {
-            var nameObj = {name: name, capital: capitalNames[index]};
+            var nameObj = {
+                name: name,
+                capital: capitalNames[index]
+            } as NameObj;
 
             for (var j = 0; j < attrs.length; j++) {
-                nameObj[attrs[j]] = name + capitalAttrs[j];
+                nameObj[attrs[j]] = (name + capitalAttrs[j]) as never;
             }
 
             callback.call(context, nameObj);
@@ -66,17 +74,17 @@ export function createNameEach(names, attrs) {
  * Iterate each dimension name.
  *
  * @public
- * @param {Function} callback The parameter is like:
+ * @param callback The parameter is like:
  *                            {
  *                                name: 'angle',
  *                                capital: 'Angle',
  *                                axis: 'angleAxis',
- *                                axisIndex: 'angleAixs',
+ *                                axisIndex: 'angleAxisIndex',
  *                                index: 'angleIndex'
  *                            }
- * @param {Object} context
+ * @param context
  */
-export var eachAxisDim = createNameEach(AXIS_DIMS, ['axisIndex', 'axis', 'index', 'id']);
+export var eachAxisDim = createNameEach(AXIS_DIMS);
 
 /**
  * If tow dataZoomModels has the same axis controlled, we say that they are 'linked'.
@@ -84,17 +92,26 @@ export var eachAxisDim = createNameEach(AXIS_DIMS, ['axisIndex', 'axis', 'index'
  * This function finds the graphic where the source dataZoomModel is in.
  *
  * @public
- * @param {Function} forEachNode Node iterator.
- * @param {Function} forEachEdgeType edgeType iterator
- * @param {Function} edgeIdGetter Giving node and edgeType, return an array of edge id.
- * @return {Function} Input: sourceNode, Output: Like {nodes: [], dims: {}}
+ * @param forEachNode Node iterator.
+ * @param forEachEdgeType edgeType iterator
+ * @param edgeIdGetter Giving node and edgeType, return an array of edge id.
+ * @return Input: sourceNode, Output: Like {nodes: [], dims: {}}
  */
-export function createLinkedNodesFinder(forEachNode, forEachEdgeType, edgeIdGetter) {
-
-    return function (sourceNode) {
-        var result = {
+export function createLinkedNodesFinder<N, E extends {name: string}>(
+    forEachNode: (cb: (node: N) => void) => void,
+    forEachEdgeType: (cb: (edge: E) => void) => void,
+    edgeIdGetter: (node: N, edge: E) => number[]
+) {
+
+    type Result = {
+        nodes: N[]
+        // key: edgeType.name, value: Object (key: edge id, value: boolean).
+        records: Dictionary<Dictionary<boolean>>
+    }
+    return function (sourceNode: N) {
+        var result: Result = {
             nodes: [],
-            records: {} // key: edgeType.name, value: Object (key: edge id, value: boolean).
+            records: {}
         };
 
         forEachEdgeType(function (edgeType) {
@@ -114,7 +131,7 @@ export function createLinkedNodesFinder(forEachNode, forEachEdgeType, edgeIdGett
         }
         while (existsLink);
 
-        function processSingleNode(node) {
+        function processSingleNode(node: N) {
             if (!isNodeAbsorded(node, result) && isLinked(node, result)) {
                 absorb(node, result);
                 existsLink = true;
@@ -124,13 +141,13 @@ export function createLinkedNodesFinder(forEachNode, forEachEdgeType, edgeIdGett
         return result;
     };
 
-    function isNodeAbsorded(node, result) {
+    function isNodeAbsorded(node: N, result: Result) {
         return zrUtil.indexOf(result.nodes, node) >= 0;
     }
 
-    function isLinked(node, result) {
+    function isLinked(node: N, result: Result) {
         var hasLink = false;
-        forEachEdgeType(function (edgeType) {
+        forEachEdgeType(function (edgeType: E) {
             zrUtil.each(edgeIdGetter(node, edgeType) || [], function (edgeId) {
                 result.records[edgeType.name][edgeId] && (hasLink = true);
             });
@@ -138,9 +155,9 @@ export function createLinkedNodesFinder(forEachNode, forEachEdgeType, edgeIdGett
         return hasLink;
     }
 
-    function absorb(node, result) {
+    function absorb(node: N, result: Result) {
         result.nodes.push(node);
-        forEachEdgeType(function (edgeType) {
+        forEachEdgeType(function (edgeType: E) {
             zrUtil.each(edgeIdGetter(node, edgeType) || [], function (edgeId) {
                 result.records[edgeType.name][edgeId] = true;
             });
diff --git a/src/component/dataZoom/typeDefaulter.ts b/src/component/dataZoom/typeDefaulter.ts
index 5a8925b..e0f14f1 100644
--- a/src/component/dataZoom/typeDefaulter.ts
+++ b/src/component/dataZoom/typeDefaulter.ts
@@ -17,8 +17,6 @@
 * under the License.
 */
 
-// @ts-nocheck
-
 import Component from '../../model/Component';
 
 Component.registerSubTypeDefaulter('dataZoom', function () {
diff --git a/src/component/legend/LegendView.ts b/src/component/legend/LegendView.ts
index ebc3838..0fc63b6 100644
--- a/src/component/legend/LegendView.ts
+++ b/src/component/legend/LegendView.ts
@@ -27,7 +27,15 @@ import ComponentView from '../../view/Component';
 import LegendModel, { LegendOption, LegendSelectorButtonOption, LegendTooltipFormatterParams } from './LegendModel';
 import GlobalModel from '../../model/Global';
 import ExtensionAPI from '../../ExtensionAPI';
-import { ColorString, ZRTextAlign, ZRColor, ItemStyleOption, ZRRectLike, ECElement, CommonTooltipOption } from '../../util/types';
+import {
+    ColorString,
+    ZRTextAlign,
+    ZRColor,
+    ItemStyleOption,
+    ZRRectLike,
+    ECElement,
+    CommonTooltipOption
+} from '../../util/types';
 import Model from '../../model/Model';
 
 var curry = zrUtil.curry;
diff --git a/src/component/toolbox/feature/Brush.ts b/src/component/toolbox/feature/Brush.ts
index b126384..a4d1589 100644
--- a/src/component/toolbox/feature/Brush.ts
+++ b/src/component/toolbox/feature/Brush.ts
@@ -30,7 +30,7 @@ import ExtensionAPI from '../../../ExtensionAPI';
 
 var brushLang = lang.toolbox.brush;
 
-const ICON_TYPES =  ['rect', 'polygon', 'lineX', 'lineY', 'keep', 'clear'] as const;
+const ICON_TYPES = ['rect', 'polygon', 'lineX', 'lineY', 'keep', 'clear'] as const;
 
 type IconType = typeof ICON_TYPES[number];
 
diff --git a/src/component/toolbox/feature/MagicType.ts b/src/component/toolbox/feature/MagicType.ts
index 8740f70..95456e0 100644
--- a/src/component/toolbox/feature/MagicType.ts
+++ b/src/component/toolbox/feature/MagicType.ts
@@ -29,7 +29,7 @@ import SeriesModel from '../../../model/Series';
 const magicTypeLang = lang.toolbox.magicType;
 const INNER_STACK_KEYWORD = '__ec_magicType_stack__' as const;
 
-const ICON_TYPES =  ['line', 'bar', 'stack'] as const;
+const ICON_TYPES = ['line', 'bar', 'stack'] as const;
 
 const radioTypes = [
     ['line', 'bar'],
diff --git a/src/component/dataZoom/typeDefaulter.ts b/src/coord/AxisBaseModel.ts
similarity index 60%
copy from src/component/dataZoom/typeDefaulter.ts
copy to src/coord/AxisBaseModel.ts
index 5a8925b..18cd29a 100644
--- a/src/component/dataZoom/typeDefaulter.ts
+++ b/src/coord/AxisBaseModel.ts
@@ -17,11 +17,19 @@
 * under the License.
 */
 
-// @ts-nocheck
+/**
+ * Base Axis Model for xAxis, yAxis, angleAxis, radiusAxis. singleAxis
+ */
+import { AxisBaseOption } from './axisCommonTypes';
+import ComponentModel from '../model/Component';
+import { AxisModelCommonMixin } from './axisModelCommonMixin';
+import { AxisModelExtendedInCreator } from './axisModelCreator';
+import Axis from './Axis';
 
-import Component from '../../model/Component';
+export interface AxisBaseModel<T extends AxisBaseOption = AxisBaseOption>
+    extends ComponentModel<T>,
+    AxisModelCommonMixin<T>,
+    AxisModelExtendedInCreator<T> {
 
-Component.registerSubTypeDefaulter('dataZoom', function () {
-    // Default 'slider' when no type specified.
-    return 'slider';
-});
+    axis: Axis
+}
\ No newline at end of file
diff --git a/src/coord/axisCommonTypes.ts b/src/coord/axisCommonTypes.ts
index b20355c..fa0be78 100644
--- a/src/coord/axisCommonTypes.ts
+++ b/src/coord/axisCommonTypes.ts
@@ -22,6 +22,7 @@ import {
     AreaStyleOption, ComponentOption, OptionDataValue
 } from '../util/types';
 import { Dictionary } from 'zrender/src/core/types';
+import { AxisModelCommonMixin } from './axisModelCommonMixin';
 
 
 export var AXIS_TYPES = {value: 1, category: 1, time: 1, log: 1} as const;
@@ -201,4 +202,4 @@ interface SplitAreaOption {
     interval?: 'auto' | number | ((index:number, value: string) => boolean)
     // colors will display in turn
     areaStyle?: AreaStyleOption<ZRColor | ZRColor[]>
-}
+}
\ No newline at end of file
diff --git a/src/coord/axisHelper.ts b/src/coord/axisHelper.ts
index 7cb3fb4..c536824 100644
--- a/src/coord/axisHelper.ts
+++ b/src/coord/axisHelper.ts
@@ -261,7 +261,7 @@ export function createScaleByModel(model: Model<ComponentOption>, axisType?: str
             case 'time':
                 return new TimeScale({
                     useUTC: model.ecModel.get('useUTC')
-                })
+                });
             default:
                 // case 'value'/'interval', 'log', or others.
                 return new (Scale.getClass(axisType) || IntervalScale)();
diff --git a/src/coord/axisModelCreator.ts b/src/coord/axisModelCreator.ts
index a2c161c..b920d10 100644
--- a/src/coord/axisModelCreator.ts
+++ b/src/coord/axisModelCreator.ts
@@ -33,6 +33,11 @@ import GlobalModel from '../model/Global';
 
 type Constructor<T> = new (...args: any[]) => T;
 
+export interface AxisModelExtendedInCreator<Opt extends AxisBaseOption> {
+    getCategories(rawData?: boolean): OrdinalRawValue[] | Opt['data']
+    getOrdinalMeta(): OrdinalMeta
+}
+
 /**
  * Generate sub axis model class
  * @param axisName 'x' 'y' 'radius' 'angle' 'parallel' ...
@@ -53,7 +58,7 @@ export default function <
             extraDefaultOption, true
         );
 
-        class AxisModel extends BaseAxisModelClass {
+        class AxisModel extends BaseAxisModelClass implements AxisModelExtendedInCreator<AxisOptionT> {
 
             static type = axisName + 'Axis.' + axisType;
             type = axisName + 'Axis.' + axisType;
@@ -93,7 +98,7 @@ export default function <
              * Should not be called before all of 'getInitailData' finished.
              * Because categories are collected during initializing data.
              */
-            getCategories(rawData: boolean): OrdinalRawValue[] | AxisBaseOption['data'] {
+            getCategories(rawData?: boolean): OrdinalRawValue[] | AxisBaseOption['data'] {
                 var option = this.option;
                 // FIXME
                 // warning if called before all of 'getInitailData' finished.
diff --git a/src/coord/cartesian/Axis2D.ts b/src/coord/cartesian/Axis2D.ts
index 9214d74..6253cb0 100644
--- a/src/coord/cartesian/Axis2D.ts
+++ b/src/coord/cartesian/Axis2D.ts
@@ -20,7 +20,7 @@
 import Axis from '../Axis';
 import { DimensionName } from '../../util/types';
 import Scale from '../../scale/Scale';
-import AxisModel, { CartesianAxisPosition } from './AxisModel';
+import CartesianAxisModel, { CartesianAxisPosition } from './AxisModel';
 import Grid from './Grid';
 import { OptionAxisType } from '../axisCommonTypes';
 
@@ -67,7 +67,7 @@ class Axis2D extends Axis {
     /**
      * Axis model. Injected outside
      */
-    model: AxisModel;
+    model: CartesianAxisModel;
 
     /**
      * Injected outside.
diff --git a/src/coord/cartesian/AxisModel.ts b/src/coord/cartesian/AxisModel.ts
index 890a51c..454cf0e 100644
--- a/src/coord/cartesian/AxisModel.ts
+++ b/src/coord/cartesian/AxisModel.ts
@@ -19,11 +19,12 @@
 
 import * as zrUtil from 'zrender/src/core/util';
 import ComponentModel from '../../model/Component';
-import axisModelCreator from '../axisModelCreator';
+import axisModelCreator, { AxisModelExtendedInCreator } from '../axisModelCreator';
 import {AxisModelCommonMixin} from '../axisModelCommonMixin';
 import Axis2D from './Axis2D';
 import { AxisBaseOption } from '../axisCommonTypes';
 import GridModel from './GridModel';
+import { AxisBaseModel } from '../AxisBaseModel';
 
 
 export type CartesianAxisPosition = 'top' | 'bottom' | 'left' | 'right';
@@ -36,7 +37,8 @@ interface CartesianAxisOption extends AxisBaseOption {
     offset?: number;
 }
 
-class AxisModel extends ComponentModel<CartesianAxisOption> {
+class CartesianAxisModel extends ComponentModel<CartesianAxisOption>
+    implements AxisBaseModel<CartesianAxisOption> {
 
     static type = 'cartesian2dAxis';
 
@@ -66,10 +68,12 @@ class AxisModel extends ComponentModel<CartesianAxisOption> {
     }
 }
 
-ComponentModel.registerClass(AxisModel);
+ComponentModel.registerClass(CartesianAxisModel);
 
-interface AxisModel extends AxisModelCommonMixin<CartesianAxisOption> {}
-zrUtil.mixin(AxisModel, AxisModelCommonMixin);
+interface CartesianAxisModel extends AxisModelCommonMixin<CartesianAxisOption>,
+    AxisModelExtendedInCreator<CartesianAxisOption> {}
+
+zrUtil.mixin(CartesianAxisModel, AxisModelCommonMixin);
 
 var extraOption: CartesianAxisOption = {
     // gridIndex: 0,
@@ -77,7 +81,7 @@ var extraOption: CartesianAxisOption = {
     offset: 0
 };
 
-axisModelCreator<CartesianAxisOption, typeof AxisModel>('x', AxisModel, extraOption);
-axisModelCreator<CartesianAxisOption, typeof AxisModel>('y', AxisModel, extraOption);
+axisModelCreator<CartesianAxisOption, typeof CartesianAxisModel>('x', CartesianAxisModel, extraOption);
+axisModelCreator<CartesianAxisOption, typeof CartesianAxisModel>('y', CartesianAxisModel, extraOption);
 
-export default AxisModel;
+export default CartesianAxisModel;
diff --git a/src/coord/cartesian/Grid.ts b/src/coord/cartesian/Grid.ts
index 200cf6e..288af99 100644
--- a/src/coord/cartesian/Grid.ts
+++ b/src/coord/cartesian/Grid.ts
@@ -40,7 +40,7 @@ import {ParsedModelFinder} from '../../util/model';
 
 // Depends on GridModel, AxisModel, which performs preprocess.
 import GridModel from './GridModel';
-import AxisModel from './AxisModel';
+import CartesianAxisModel from './AxisModel';
 import GlobalModel from '../../model/Global';
 import ExtensionAPI from '../../ExtensionAPI';
 import { Dictionary } from 'zrender/src/core/types';
@@ -349,7 +349,7 @@ class Grid implements CoordinateSystemMaster {
         }, this);
 
         function createAxisCreator(dimName: Cartesian2DDimensionName) {
-            return function (axisModel: AxisModel, idx: number): void {
+            return function (axisModel: CartesianAxisModel, idx: number): void {
                 if (!isAxisUsedInTheGrid(axisModel, gridModel)) {
                     return;
                 }
@@ -526,7 +526,7 @@ class Grid implements CoordinateSystemMaster {
 /**
  * Check if the axis is used in the specified grid.
  */
-function isAxisUsedInTheGrid(axisModel: AxisModel, gridModel: GridModel): boolean {
+function isAxisUsedInTheGrid(axisModel: CartesianAxisModel, gridModel: GridModel): boolean {
     return axisModel.getCoordSysModel() === gridModel;
 }
 
@@ -613,9 +613,9 @@ function updateAxisTransform(axis: Axis2D, coordBase: number) {
 }
 
 var axesTypes = ['xAxis', 'yAxis'];
-function findAxesModels(seriesModel: SeriesModel): AxisModel[] {
+function findAxesModels(seriesModel: SeriesModel): CartesianAxisModel[] {
     return map(axesTypes, function (axisType) {
-        var axisModel = seriesModel.getReferringComponents(axisType)[0] as AxisModel;
+        var axisModel = seriesModel.getReferringComponents(axisType)[0] as CartesianAxisModel;
 
         if (__DEV__) {
             if (!axisModel) {
diff --git a/src/coord/cartesian/cartesianAxisHelper.ts b/src/coord/cartesian/cartesianAxisHelper.ts
index 21004d9..5d11aa7 100644
--- a/src/coord/cartesian/cartesianAxisHelper.ts
+++ b/src/coord/cartesian/cartesianAxisHelper.ts
@@ -20,7 +20,7 @@
 
 import * as zrUtil from 'zrender/src/core/util';
 import GridModel from './GridModel';
-import AxisModel from './AxisModel';
+import CartesianAxisModel from './AxisModel';
 
 interface CartesianAxisLayout {
     position: [number, number];
@@ -38,7 +38,7 @@ interface CartesianAxisLayout {
  * (Can be called before coordinate system update stage).
  */
 export function layout(
-    gridModel: GridModel, axisModel: AxisModel, opt?: {labelInside?: boolean}
+    gridModel: GridModel, axisModel: CartesianAxisModel, opt?: {labelInside?: boolean}
 ): CartesianAxisLayout {
     opt = opt || {};
     var grid = gridModel.coordinateSystem;
diff --git a/src/coord/polar/AxisModel.ts b/src/coord/polar/AxisModel.ts
index 244f7e6..1d41b92 100644
--- a/src/coord/polar/AxisModel.ts
+++ b/src/coord/polar/AxisModel.ts
@@ -19,11 +19,12 @@
 
 import * as zrUtil from 'zrender/src/core/util';
 import ComponentModel from '../../model/Component';
-import axisModelCreator from '../axisModelCreator';
+import axisModelCreator, { AxisModelExtendedInCreator } from '../axisModelCreator';
 import {AxisModelCommonMixin} from '../axisModelCommonMixin';
 import { AxisBaseOption } from '../axisCommonTypes';
 import AngleAxis from './AngleAxis';
 import RadiusAxis from './RadiusAxis';
+import { AxisBaseModel } from '../AxisBaseModel';
 
 export interface AngleAxisOption extends AxisBaseOption {
     /**
@@ -58,7 +59,8 @@ export interface RadiusAxisOption extends AxisBaseOption {
 
 type PolarAxisOption = AngleAxisOption | RadiusAxisOption;
 
-class PolarAxisModel<T extends PolarAxisOption = PolarAxisOption> extends ComponentModel<T> {
+class PolarAxisModel<T extends PolarAxisOption = PolarAxisOption> extends ComponentModel<T>
+    implements AxisBaseModel<T> {
     static type = 'polarAxis'
 
     getCoordSysModel(): ComponentModel {
@@ -70,7 +72,9 @@ class PolarAxisModel<T extends PolarAxisOption = PolarAxisOption> extends Compon
     }
 }
 
-interface PolarAxisModel<T extends PolarAxisOption = PolarAxisOption> extends AxisModelCommonMixin<T> {}
+interface PolarAxisModel<T extends PolarAxisOption = PolarAxisOption>
+    extends AxisModelCommonMixin<T>, AxisModelExtendedInCreator<T> {}
+
 zrUtil.mixin(PolarAxisModel, AxisModelCommonMixin);
 
 export {PolarAxisModel};
diff --git a/src/coord/polar/Polar.ts b/src/coord/polar/Polar.ts
index 4b7e3af..b711d3e 100644
--- a/src/coord/polar/Polar.ts
+++ b/src/coord/polar/Polar.ts
@@ -236,16 +236,21 @@ class Polar implements CoordinateSystem, CoordinateSystemMaster {
     }
 
     convertToPixel(ecModel: GlobalModel, finder: ParsedModelFinder, value: ScaleDataValue[]) {
-        const seriesModel = finder.seriesModel;
-        const coordSys = seriesModel && seriesModel.coordinateSystem;
+        const coordSys = getCoordSys(finder);
         return coordSys === this ? this.dataToPoint(value) : null;
     }
 
     convertFromPixel(ecModel: GlobalModel, finder: ParsedModelFinder, pixel: number[]) {
-        const seriesModel = finder.seriesModel;
-        const coordSys = seriesModel && seriesModel.coordinateSystem;
+        const coordSys = getCoordSys(finder);
         return coordSys === this ? this.pointToData(pixel) : null;
     }
 }
 
+function getCoordSys(finder: ParsedModelFinder) {
+    const seriesModel = finder.seriesModel;
+    const polarModel = finder.polarModel as PolarModel;
+    return polarModel && polarModel.coordinateSystem
+        || seriesModel && seriesModel.coordinateSystem as Polar;
+}
+
 export default Polar;
\ No newline at end of file
diff --git a/src/coord/single/AxisModel.ts b/src/coord/single/AxisModel.ts
index 7f302d0..5dd4edb 100644
--- a/src/coord/single/AxisModel.ts
+++ b/src/coord/single/AxisModel.ts
@@ -19,12 +19,13 @@
 
 import * as zrUtil from 'zrender/src/core/util';
 import ComponentModel from '../../model/Component';
-import axisModelCreator from '../axisModelCreator';
+import axisModelCreator, { AxisModelExtendedInCreator } from '../axisModelCreator';
 import {AxisModelCommonMixin} from '../axisModelCommonMixin';
 import Single from './Single';
 import SingleAxis from './SingleAxis';
 import { AxisBaseOption } from '../axisCommonTypes';
 import { BoxLayoutOptionMixin, LayoutOrient } from '../../util/types';
+import { AxisBaseModel } from '../AxisBaseModel';
 
 export type SingleAxisPosition = 'top' | 'bottom' | 'left' | 'right'
 
@@ -33,7 +34,8 @@ export interface SingleAxisOption extends AxisBaseOption, BoxLayoutOptionMixin {
     orient: LayoutOrient
 }
 
-class SingleAxisModel extends ComponentModel<SingleAxisOption> {
+class SingleAxisModel extends ComponentModel<SingleAxisOption>
+    implements AxisBaseModel<SingleAxisOption>  {
     static type = 'singleAxis'
     type = SingleAxisModel.type
 
@@ -100,7 +102,9 @@ class SingleAxisModel extends ComponentModel<SingleAxisOption> {
 
 ComponentModel.registerClass(SingleAxisModel);
 
-interface SingleAxisModel extends AxisModelCommonMixin<SingleAxisOption> {}
+interface SingleAxisModel extends AxisModelCommonMixin<SingleAxisOption>,
+    AxisModelExtendedInCreator<SingleAxisOption> {}
+
 zrUtil.mixin(SingleAxisModel, {AxisModelCommonMixin});
 
 axisModelCreator('single', SingleAxisModel, SingleAxisModel.defaultOption);
diff --git a/src/coord/single/Single.ts b/src/coord/single/Single.ts
index 35457be..26313b6 100644
--- a/src/coord/single/Single.ts
+++ b/src/coord/single/Single.ts
@@ -239,16 +239,21 @@ class Single implements CoordinateSystem, CoordinateSystemMaster {
     }
 
     convertToPixel(ecModel: GlobalModel, finder: ParsedModelFinder, value: ScaleDataValue[]) {
-        const seriesModel = finder.seriesModel;
-        const coordSys = seriesModel && seriesModel.coordinateSystem;
+        const coordSys = getCoordSys(finder);
         return coordSys === this ? this.dataToPoint(value) : null;
     }
 
     convertFromPixel(ecModel: GlobalModel, finder: ParsedModelFinder, pixel: number[]) {
-        const seriesModel = finder.seriesModel;
-        const coordSys = seriesModel && seriesModel.coordinateSystem;
+        const coordSys = getCoordSys(finder);
         return coordSys === this ? this.pointToData(pixel) : null;
     }
 }
 
+function getCoordSys(finder: ParsedModelFinder) {
+    const seriesModel = finder.seriesModel;
+    const polarModel = finder.singleAxisModel as SingleAxisModel;
+    return polarModel && polarModel.coordinateSystem
+        || seriesModel && seriesModel.coordinateSystem as Single;
+}
+
 export default Single;
diff --git a/src/data/List.ts b/src/data/List.ts
index e82d3a6..75afe4f 100644
--- a/src/data/List.ts
+++ b/src/data/List.ts
@@ -1157,11 +1157,11 @@ class List <HostModel extends Model = Model> {
     /**
      * Data filter
      */
-    filterSelf<Ctx>(cb: FilterCb0<Ctx>, ctx?: Ctx, ctxCompat?: Ctx): List;
-    filterSelf<Ctx>(dims: DimensionLoose, cb: FilterCb1<Ctx>, ctx?: Ctx, ctxCompat?: Ctx): List;
-    filterSelf<Ctx>(dims: [DimensionLoose], cb: FilterCb1<Ctx>, ctx?: Ctx, ctxCompat?: Ctx): List;
-    filterSelf<Ctx>(dims: [DimensionLoose, DimensionLoose], cb: FilterCb2<Ctx>, ctx?: Ctx, ctxCompat?: Ctx): List;
-    filterSelf<Ctx>(dims: ItrParamDims, cb: FilterCb<Ctx>, ctx?: Ctx, ctxCompat?: Ctx): List;
+    filterSelf<Ctx>(cb: FilterCb0<Ctx>, ctx?: Ctx, ctxCompat?: Ctx): this;
+    filterSelf<Ctx>(dims: DimensionLoose, cb: FilterCb1<Ctx>, ctx?: Ctx, ctxCompat?: Ctx): this;
+    filterSelf<Ctx>(dims: [DimensionLoose], cb: FilterCb1<Ctx>, ctx?: Ctx, ctxCompat?: Ctx): this;
+    filterSelf<Ctx>(dims: [DimensionLoose, DimensionLoose], cb: FilterCb2<Ctx>, ctx?: Ctx, ctxCompat?: Ctx): this;
+    filterSelf<Ctx>(dims: ItrParamDims, cb: FilterCb<Ctx>, ctx?: Ctx, ctxCompat?: Ctx): this;
     filterSelf<Ctx>(
         dims: ItrParamDims | FilterCb<Ctx>,
         cb: FilterCb<Ctx> | Ctx,
@@ -1242,7 +1242,7 @@ class List <HostModel extends Model = Model> {
      * Select data in range. (For optimization of filter)
      * (Manually inline code, support 5 million data filtering in data zoom.)
      */
-    selectRange(range: {[dimName: string]: string}): List {
+    selectRange(range: {[dimName: string]: [number, number]}): List {
         'use strict';
 
         if (!this._count) {
@@ -1410,9 +1410,9 @@ class List <HostModel extends Model = Model> {
     /**
      * Data mapping to a new List with given dimensions
      */
-    map<Ctx>(dims: DimensionLoose, cb: MapCb1<Ctx>, ctx?: Ctx, ctxCompat?: Ctx): List;
-    map<Ctx>(dims: [DimensionLoose], cb: MapCb1<Ctx>, ctx?: Ctx, ctxCompat?: Ctx): List;
-    map<Ctx>(dims: [DimensionLoose, DimensionLoose], cb: MapCb2<Ctx>, ctx?: Ctx, ctxCompat?: Ctx): List;
+    map<Ctx>(dims: DimensionLoose, cb: MapCb1<Ctx>, ctx?: Ctx, ctxCompat?: Ctx): List<HostModel>;
+    map<Ctx>(dims: [DimensionLoose], cb: MapCb1<Ctx>, ctx?: Ctx, ctxCompat?: Ctx): List<HostModel>;
+    map<Ctx>(dims: [DimensionLoose, DimensionLoose], cb: MapCb2<Ctx>, ctx?: Ctx, ctxCompat?: Ctx): List<HostModel>;
     map<Ctx>(
         dims: ItrParamDims,
         cb: MapCb<Ctx>,
@@ -1498,7 +1498,7 @@ class List <HostModel extends Model = Model> {
         rate: number,
         sampleValue: (frameValues: ParsedValue[]) => ParsedValueNumeric,
         sampleIndex: (frameValues: ParsedValue[], value: ParsedValueNumeric) => number
-    ): List {
+    ): List<HostModel> {
         var list = cloneListForMapAndSample(this, [dimension]);
         var targetStorage = list._storage;
 
@@ -1549,7 +1549,7 @@ class List <HostModel extends Model = Model> {
 
         list.getRawIndex = getRawIndexWithIndices;
 
-        return list;
+        return list as List<HostModel>;
     }
 
     /**
diff --git a/src/model/mixin/areaStyle.ts b/src/model/mixin/areaStyle.ts
index 4d1f63e..ca404c8 100644
--- a/src/model/mixin/areaStyle.ts
+++ b/src/model/mixin/areaStyle.ts
@@ -20,6 +20,7 @@
 import makeStyleMapper from './makeStyleMapper';
 import { StyleProps } from 'zrender/src/graphic/Style';
 import Model from '../Model';
+import { AreaStyleOption } from '../../util/types';
 
 var getAreaStyle = makeStyleMapper([
     ['fill', 'color'],
@@ -40,7 +41,11 @@ type AreaStyleProps = Pick<StyleProps,
 >
 
 class AreaStyleMixin {
-    getAreaStyle(this: Model, excludes?: string[], includes?: string[]): AreaStyleProps {
+    getAreaStyle(
+        this: Model,
+        excludes?: (keyof AreaStyleOption)[],
+        includes?: (keyof AreaStyleOption)[]
+    ): AreaStyleProps {
         return getAreaStyle(this, excludes, includes);
     }
 };
diff --git a/src/model/mixin/itemStyle.ts b/src/model/mixin/itemStyle.ts
index ccf5fc5..5eb57ca 100644
--- a/src/model/mixin/itemStyle.ts
+++ b/src/model/mixin/itemStyle.ts
@@ -20,6 +20,7 @@
 import makeStyleMapper from './makeStyleMapper';
 import Model from '../Model';
 import { StyleProps } from 'zrender/src/graphic/Style';
+import { ItemStyleOption } from '../../util/types';
 
 var getItemStyle = makeStyleMapper([
     ['fill', 'color'],
@@ -30,12 +31,12 @@ var getItemStyle = makeStyleMapper([
     ['shadowOffsetX'],
     ['shadowOffsetY'],
     ['shadowColor'],
+    // TODO?
     ['textPosition'],
     ['textAlign']
 ]);
 
-type ItemStyleProps = Pick<StyleProps,
-    'fill'
+type ItemStyleKeys = 'fill'
     | 'stroke'
     | 'lineWidth'
     | 'opacity'
@@ -45,11 +46,12 @@ type ItemStyleProps = Pick<StyleProps,
     | 'shadowColor'
     | 'textPosition'
     | 'textAlign'
->
+
+type ItemStyleProps = Pick<StyleProps, ItemStyleKeys>
 
 class ItemStyleMixin {
 
-    getItemStyle(this: Model, excludes?: string[], includes?: string[]): ItemStyleProps {
+    getItemStyle(this: Model, excludes?: (keyof ItemStyleOption)[], includes?: (keyof ItemStyleOption)[]): ItemStyleProps {
         var style = getItemStyle(this, excludes, includes);
         var lineDash = this.getBorderLineDash();
         lineDash && ((style as any).lineDash = lineDash);
diff --git a/src/model/mixin/lineStyle.ts b/src/model/mixin/lineStyle.ts
index cb28c3d..c28e75b 100644
--- a/src/model/mixin/lineStyle.ts
+++ b/src/model/mixin/lineStyle.ts
@@ -20,6 +20,7 @@
 import makeStyleMapper from './makeStyleMapper';
 import Model from '../Model';
 import { StyleProps } from 'zrender/src/graphic/Style';
+import { LineStyleOption } from '../../util/types';
 
 var getLineStyle = makeStyleMapper([
     ['lineWidth', 'width'],
@@ -31,19 +32,19 @@ var getLineStyle = makeStyleMapper([
     ['shadowColor']
 ]);
 
-type LineStyleProps = Pick<StyleProps,
-    'lineWidth'
+type LineStyleKeys = 'lineWidth'
     | 'stroke'
     | 'opacity'
     | 'shadowBlur'
     | 'shadowOffsetX'
     | 'shadowOffsetY'
     | 'shadowColor'
->
+
+type LineStyleProps = Pick<StyleProps, LineStyleKeys>
 
 class LineStyleMixin {
 
-    getLineStyle(this: Model, excludes?: string[]): LineStyleProps {
+    getLineStyle(this: Model, excludes?: (keyof LineStyleOption)[]): LineStyleProps {
         var style = getLineStyle(this, excludes);
         // Always set lineDash whether dashed, otherwise we can not
         // erase the previous style when assigning to el.style.
diff --git a/src/util/model.ts b/src/util/model.ts
index 10fcc11..482310d 100644
--- a/src/util/model.ts
+++ b/src/util/model.ts
@@ -45,7 +45,7 @@ import {
 } from './types';
 import { Dictionary } from 'zrender/src/core/types';
 import SeriesModel from '../model/Series';
-import AxisModel from '../coord/cartesian/AxisModel';
+import CartesianAxisModel from '../coord/cartesian/AxisModel';
 import GridModel from '../coord/cartesian/GridModel';
 
 /**
@@ -516,10 +516,10 @@ export type ModelFinderObject = {
 export type ParsedModelFinder = {
     seriesModels?: SeriesModel[],
     seriesModel?: SeriesModel,
-    xAxisModels?: AxisModel[],
-    xAxisModel?: AxisModel,
-    yAxisModels?: AxisModel[],
-    yAxisModel?: AxisModel,
+    xAxisModels?: CartesianAxisModel[],
+    xAxisModel?: CartesianAxisModel,
+    yAxisModels?: CartesianAxisModel[],
+    yAxisModel?: CartesianAxisModel,
     gridModels?: GridModel[],
     gridModel?: GridModel,
     // others:
diff --git a/src/util/types.ts b/src/util/types.ts
index 059de8a..ee5717e 100644
--- a/src/util/types.ts
+++ b/src/util/types.ts
@@ -637,6 +637,7 @@ export interface LineStyleOption<Clr = ZRColor> extends ShadowOptionMixin {
  */
 export interface AreaStyleOption<Clr = ZRColor> extends ShadowOptionMixin {
     color?: Clr
+    opacity?: number
 }
 
 type Arrayable<T extends Dictionary<any>> = { [key in keyof T]: T[key] | T[key][] }
@@ -906,3 +907,24 @@ export interface SeriesOption extends
 
     // FIXME:TS more
 }
+
+export interface SeriesOnCartesianOptionMixin {
+    xAxisIndex?: number
+    yAxisIndex?: number
+
+    xAxisId?: string
+    yAxisId?: string
+}
+
+export interface SeriesOnPolarOptionMixin {
+    radiusAxisIndex?: number
+    angleAxisIndex?: number
+
+    radiusAxisId?: string
+    angleAxisId?: string
+}
+
+export interface SeriesOnSingleOptionMixin {
+    singleAxisIndex?: number
+    singleAxisId?: string
+}
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@echarts.apache.org
For additional commands, e-mail: commits-help@echarts.apache.org