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/22 13:16:42 UTC

[incubator-echarts] branch typescript updated: ts: finish types on visualMap component

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 df99989  ts: finish types on visualMap component
df99989 is described below

commit df999899a85374d82663a199f1bd86a82bb75f91
Author: pissang <bm...@gmail.com>
AuthorDate: Sat Feb 22 21:16:11 2020 +0800

    ts: finish types on visualMap component
---
 src/component/helper/sliderMove.ts         |  29 +-
 src/component/visualMap/ContinuousModel.ts |   6 +-
 src/component/visualMap/ContinuousView.ts  | 418 ++++++++++++++---------------
 src/component/visualMap/PiecewiseModel.ts  |  27 +-
 src/component/visualMap/PiecewiseView.ts   |  93 ++++---
 src/component/visualMap/VisualMapModel.ts  |  11 +-
 src/component/visualMap/VisualMapView.ts   | 122 +++++----
 src/component/visualMap/helper.ts          |  12 +-
 src/component/visualMap/preprocessor.ts    |   3 +-
 src/coord/axisModelCreator.ts              |   3 +-
 src/data/OrdinalMeta.ts                    |   3 +
 src/export.ts                              |  54 ++--
 src/util/graphic.ts                        |   4 +-
 src/util/layout.ts                         |   6 +-
 src/util/model.ts                          |  45 ++--
 src/util/number.ts                         |   4 +-
 src/util/types.ts                          |   6 +-
 src/view/Component.ts                      |  10 +-
 18 files changed, 436 insertions(+), 420 deletions(-)

diff --git a/src/component/helper/sliderMove.ts b/src/component/helper/sliderMove.ts
index e3ed8d5..95cdc35 100644
--- a/src/component/helper/sliderMove.ts
+++ b/src/component/helper/sliderMove.ts
@@ -17,8 +17,6 @@
 * under the License.
 */
 
-// @ts-nocheck
-
 /**
  * Calculate slider move result.
  * Usage:
@@ -26,20 +24,27 @@
  * maxSpan and the same as `Math.abs(handleEnd[1] - handleEnds[0])`.
  * (2) If handle0 is forbidden to cross handle1, set minSpan as `0`.
  *
- * @param {number} delta Move length.
- * @param {Array.<number>} handleEnds handleEnds[0] can be bigger then handleEnds[1].
+ * @param delta Move length.
+ * @param handleEnds handleEnds[0] can be bigger then handleEnds[1].
  *              handleEnds will be modified in this method.
- * @param {Array.<number>} extent handleEnds is restricted by extent.
+ * @param extent handleEnds is restricted by extent.
  *              extent[0] should less or equals than extent[1].
- * @param {number|string} handleIndex Can be 'all', means that both move the two handleEnds.
- * @param {number} [minSpan] The range of dataZoom can not be smaller than that.
+ * @param handleIndex Can be 'all', means that both move the two handleEnds.
+ * @param minSpan The range of dataZoom can not be smaller than that.
  *              If not set, handle0 and cross handle1. If set as a non-negative
  *              number (including `0`), handles will push each other when reaching
  *              the minSpan.
- * @param {number} [maxSpan] The range of dataZoom can not be larger than that.
- * @return {Array.<number>} The input handleEnds.
+ * @param maxSpan The range of dataZoom can not be larger than that.
+ * @return The input handleEnds.
  */
-export default function (delta, handleEnds, extent, handleIndex, minSpan, maxSpan) {
+export default function (
+    delta: number,
+    handleEnds: number[],
+    extent: number[],
+    handleIndex: 'all' | 0 | 1,
+    minSpan?: number,
+    maxSpan?: number
+): number[] {
 
     delta = delta || 0;
 
@@ -90,14 +95,14 @@ export default function (delta, handleEnds, extent, handleIndex, minSpan, maxSpa
     return handleEnds;
 }
 
-function getSpanSign(handleEnds, handleIndex) {
+function getSpanSign(handleEnds: number[], handleIndex: 0 | 1) {
     var dist = handleEnds[handleIndex] - handleEnds[1 - handleIndex];
     // If `handleEnds[0] === handleEnds[1]`, always believe that handleEnd[0]
     // is at left of handleEnds[1] for non-cross case.
     return {span: Math.abs(dist), sign: dist > 0 ? -1 : dist < 0 ? 1 : handleIndex ? -1 : 1};
 }
 
-function restrict(value, extend) {
+function restrict(value: number, extend: number[]) {
     return Math.min(
         extend[1] != null ? extend[1] : Infinity,
         Math.max(extend[0] != null ? extend[0] : -Infinity, value)
diff --git a/src/component/visualMap/ContinuousModel.ts b/src/component/visualMap/ContinuousModel.ts
index d9cecc0..85bdff1 100644
--- a/src/component/visualMap/ContinuousModel.ts
+++ b/src/component/visualMap/ContinuousModel.ts
@@ -259,11 +259,13 @@ class ContinuousModel extends VisualMapModel<ContinousVisualMapOption> {
         };
     }
 
-    static defaultOption: ContinousVisualMapOption = {
+    static defaultOption = zrUtil.merge(
+        zrUtil.clone(VisualMapModel.defaultOption),
+    {
         align: 'auto',           // 'auto', 'left', 'right', 'top', 'bottom'
         calculable: false,
         hoverLink: true
-    }
+    }) as ContinousVisualMapOption
 }
 
 
diff --git a/src/component/visualMap/ContinuousView.ts b/src/component/visualMap/ContinuousView.ts
index f2bdc71..6732caf 100644
--- a/src/component/visualMap/ContinuousView.ts
+++ b/src/component/visualMap/ContinuousView.ts
@@ -17,10 +17,8 @@
 * under the License.
 */
 
-// @ts-nocheck
-
 import * as zrUtil from 'zrender/src/core/util';
-import LinearGradient from 'zrender/src/graphic/LinearGradient';
+import LinearGradient, { LinearGradientObject } from 'zrender/src/graphic/LinearGradient';
 import * as eventTool from 'zrender/src/core/event';
 import VisualMapView from './VisualMapView';
 import * as graphic from '../../util/graphic';
@@ -28,6 +26,14 @@ import * as numberUtil from '../../util/number';
 import sliderMove from '../helper/sliderMove';
 import * as helper from './helper';
 import * as modelUtil from '../../util/model';
+import ComponentView from '../../view/Component';
+import VisualMapModel from './VisualMapModel';
+import ContinuousModel from './ContinuousModel';
+import GlobalModel from '../../model/Global';
+import ExtensionAPI from '../../ExtensionAPI';
+import Element, { ElementEvent } from 'zrender/src/Element';
+import { Dictionary, TextVerticalAlign, TextAlign } from 'zrender/src/core/types';
+import { ColorString, Payload, ECElement } from '../../util/types';
 
 var linearMap = numberUtil.linearMap;
 var each = zrUtil.each;
@@ -38,6 +44,32 @@ var mathMax = Math.max;
 var HOVER_LINK_SIZE = 12;
 var HOVER_LINK_OUT = 6;
 
+type Orient = VisualMapModel['option']['orient']
+
+type ShapeStorage = {
+    handleThumbs: graphic.Polygon[]
+    handleLabelPoints: number[][]
+    handleLabels: graphic.Text[]
+
+    inRange: graphic.Polygon
+    outOfRange: graphic.Polygon
+
+    barGroup: graphic.Group
+
+    indicator: graphic.Polygon
+    indicatorLabel: graphic.Text
+    indicatorLabelPoint: number[]
+}
+
+type TargetDataIndices = ReturnType<ContinuousModel['findTargetDataIndices']>
+
+type BarVisual = {
+    barColor: LinearGradient,
+    barPoints: number[][]
+    handlesColor: ColorString[]
+}
+
+type Direction = 'left' | 'right' | 'top' | 'bottom';
 // Notice:
 // Any "interval" should be by the order of [low, high].
 // "handle0" (handleIndex === 0) maps to
@@ -46,72 +78,41 @@ var HOVER_LINK_OUT = 6;
 // high data value: this._dataInterval[1] and has high coord.
 // The logic of transform is implemented in this._createBarGroup.
 
-var ContinuousView = VisualMapView.extend({
+class ContinuousView extends VisualMapView {
+    static type = 'visualMap.continuous'
+    type = ContinuousView.type
 
-    type: 'visualMap.continuous',
+    visualMapModel: ContinuousModel
 
-    /**
-     * @override
-     */
-    init: function () {
-
-        ContinuousView.superApply(this, 'init', arguments);
-
-        /**
-         * @private
-         */
-        this._shapes = {};
-
-        /**
-         * @private
-         */
-        this._dataInterval = [];
-
-        /**
-         * @private
-         */
-        this._handleEnds = [];
-
-        /**
-         * @private
-         */
-        this._orient;
-
-        /**
-         * @private
-         */
-        this._useHandle;
-
-        /**
-         * @private
-         */
-        this._hoverLinkDataIndices = [];
-
-        /**
-         * @private
-         */
-        this._dragging;
-
-        /**
-         * @private
-         */
-        this._hovering;
-    },
+    private _shapes = {} as ShapeStorage
 
-    /**
-     * @protected
-     * @override
-     */
-    doRender: function (visualMapModel, ecModel, api, payload) {
+    private _dataInterval: number[] = []
+
+    private _handleEnds: number[] = []
+
+    private _orient: Orient
+
+    private _useHandle: boolean
+
+    private _hoverLinkDataIndices: TargetDataIndices = []
+
+    private _dragging: boolean
+
+    private _hovering: boolean
+
+
+    doRender(
+        visualMapModel: ContinuousModel,
+        ecModel: GlobalModel,
+        api: ExtensionAPI,
+        payload: {type: string, from: string}
+    ) {
         if (!payload || payload.type !== 'selectDataRange' || payload.from !== this.uid) {
             this._buildView();
         }
-    },
+    }
 
-    /**
-     * @private
-     */
-    _buildView: function () {
+    private _buildView() {
         this.group.removeAll();
 
         var visualMapModel = this.visualMapModel;
@@ -142,12 +143,9 @@ var ContinuousView = VisualMapView.extend({
         this._enableHoverLinkFromSeries();
 
         this.positionGroup(thisGroup);
-    },
+    }
 
-    /**
-     * @private
-     */
-    _renderEndsText: function (group, dataRangeText, endsIndex) {
+    private _renderEndsText(group: graphic.Group, dataRangeText: string[], endsIndex?: 0 | 1) {
         if (!dataRangeText) {
             return;
         }
@@ -167,7 +165,7 @@ var ContinuousView = VisualMapView.extend({
                 endsIndex === 0 ? -textGap : itemSize[1] + textGap
             ],
             barGroup
-        );
+        ) as number[];
         var align = this._applyTransform(
             endsIndex === 0 ? 'bottom' : 'top',
             barGroup
@@ -179,19 +177,16 @@ var ContinuousView = VisualMapView.extend({
             style: {
                 x: position[0],
                 y: position[1],
-                textVerticalAlign: orient === 'horizontal' ? 'middle' : align,
-                textAlign: orient === 'horizontal' ? align : 'center',
+                textVerticalAlign: orient === 'horizontal' ? 'middle' : align as TextVerticalAlign,
+                textAlign: orient === 'horizontal' ? align as TextAlign : 'center',
                 text: text,
                 textFont: textStyleModel.getFont(),
                 textFill: textStyleModel.getTextColor()
             }
         }));
-    },
+    }
 
-    /**
-     * @private
-     */
-    _renderBar: function (targetGroup) {
+    private _renderBar(targetGroup: graphic.Group) {
         var visualMapModel = this.visualMapModel;
         var shapes = this._shapes;
         var itemSize = visualMapModel.itemSize;
@@ -218,19 +213,22 @@ var ContinuousView = VisualMapView.extend({
             shapes.handleLabels = [];
             shapes.handleLabelPoints = [];
 
-            this._createHandle(barGroup, 0, itemSize, textSize, orient, itemAlign);
-            this._createHandle(barGroup, 1, itemSize, textSize, orient, itemAlign);
+            this._createHandle(barGroup, 0, itemSize, textSize, orient);
+            this._createHandle(barGroup, 1, itemSize, textSize, orient);
         }
 
         this._createIndicator(barGroup, itemSize, textSize, orient);
 
         targetGroup.add(barGroup);
-    },
+    }
 
-    /**
-     * @private
-     */
-    _createHandle: function (barGroup, handleIndex, itemSize, textSize, orient) {
+    private _createHandle(
+        barGroup: graphic.Group,
+        handleIndex: 0 | 1,
+        itemSize: number[],
+        textSize: number,
+        orient: Orient
+    ) {
         var onDrift = zrUtil.bind(this._dragHandle, this, handleIndex, false);
         var onDragEnd = zrUtil.bind(this._dragHandle, this, handleIndex, true);
         var handleThumb = createPolygon(
@@ -250,7 +248,7 @@ var ContinuousView = VisualMapView.extend({
         var handleLabel = new graphic.Text({
             draggable: true,
             drift: onDrift,
-            onmousemove: function (e) {
+            onmousemove(e) {
                 // Fot mobile devicem, prevent screen slider on the button.
                 eventTool.stop(e.event);
             },
@@ -276,12 +274,14 @@ var ContinuousView = VisualMapView.extend({
         shapes.handleThumbs[handleIndex] = handleThumb;
         shapes.handleLabelPoints[handleIndex] = handleLabelPoint;
         shapes.handleLabels[handleIndex] = handleLabel;
-    },
+    }
 
-    /**
-     * @private
-     */
-    _createIndicator: function (barGroup, itemSize, textSize, orient) {
+    private _createIndicator(
+        barGroup: graphic.Group,
+        itemSize: number[],
+        textSize: number,
+        orient: Orient
+    ) {
         var indicator = createPolygon([[0, 0]], 'move');
         indicator.position[0] = itemSize[0];
         indicator.attr({invisible: true, silent: true});
@@ -308,12 +308,15 @@ var ContinuousView = VisualMapView.extend({
         shapes.indicator = indicator;
         shapes.indicatorLabel = indicatorLabel;
         shapes.indicatorLabelPoint = indicatorLabelPoint;
-    },
+    }
 
-    /**
-     * @private
-     */
-    _dragHandle: function (handleIndex, isEnd, dx, dy) {
+    private _dragHandle(
+        handleIndex: 0 | 1 | 'all',
+        isEnd?: boolean,
+        // dx is event from ondragend if isEnd is true. It's not used
+        dx?: number | ElementEvent,
+        dy?: number
+    ) {
         if (!this._useHandle) {
             return;
         }
@@ -322,7 +325,7 @@ var ContinuousView = VisualMapView.extend({
 
         if (!isEnd) {
             // Transform dx, dy to bar coordination.
-            var vertex = this._applyTransform([dx, dy], this._shapes.barGroup, true);
+            var vertex = this._applyTransform([dx as number, dy], this._shapes.barGroup, true) as number[];
             this._updateInterval(handleIndex, vertex[1]);
 
             // Considering realtime, update view should be executed
@@ -344,14 +347,11 @@ var ContinuousView = VisualMapView.extend({
             !this._hovering && this._clearHoverLinkToSeries();
         }
         else if (useHoverLinkOnHandle(this.visualMapModel)) {
-            this._doHoverLinkToSeries(this._handleEnds[handleIndex], false);
+            this._doHoverLinkToSeries(this._handleEnds[handleIndex as 0 | 1], false);
         }
-    },
+    }
 
-    /**
-     * @private
-     */
-    _resetInterval: function () {
+    private _resetInterval() {
         var visualMapModel = this.visualMapModel;
 
         var dataInterval = this._dataInterval = visualMapModel.getSelected();
@@ -362,7 +362,7 @@ var ContinuousView = VisualMapView.extend({
             linearMap(dataInterval[0], dataExtent, sizeExtent, true),
             linearMap(dataInterval[1], dataExtent, sizeExtent, true)
         ];
-    },
+    }
 
     /**
      * @private
@@ -370,7 +370,7 @@ var ContinuousView = VisualMapView.extend({
      * @param {number} dx
      * @param {number} dy
      */
-    _updateInterval: function (handleIndex, delta) {
+    private _updateInterval(handleIndex: 0 | 1 | 'all', delta: number) {
         delta = delta || 0;
         var visualMapModel = this.visualMapModel;
         var handleEnds = this._handleEnds;
@@ -391,12 +391,9 @@ var ContinuousView = VisualMapView.extend({
             linearMap(handleEnds[0], sizeExtent, dataExtent, true),
             linearMap(handleEnds[1], sizeExtent, dataExtent, true)
         ];
-    },
+    }
 
-    /**
-     * @private
-     */
-    _updateView: function (forSketch) {
+    private _updateView(forSketch?: boolean) {
         var visualMapModel = this.visualMapModel;
         var dataExtent = visualMapModel.getExtent();
         var shapes = this._shapes;
@@ -413,24 +410,26 @@ var ContinuousView = VisualMapView.extend({
 
         shapes.inRange
             .setStyle({
-                fill: visualInRange.barColor,
-                opacity: visualInRange.opacity
+                fill: visualInRange.barColor
+                // opacity: visualInRange.opacity
             })
             .setShape('points', visualInRange.barPoints);
         shapes.outOfRange
             .setStyle({
-                fill: visualOutOfRange.barColor,
-                opacity: visualOutOfRange.opacity
+                fill: visualOutOfRange.barColor
+                // opacity: visualOutOfRange.opacity
             })
             .setShape('points', visualOutOfRange.barPoints);
 
         this._updateHandle(inRangeHandleEnds, visualInRange);
-    },
+    }
 
-    /**
-     * @private
-     */
-    _createBarVisual: function (dataInterval, dataExtent, handleEnds, forceState) {
+    private _createBarVisual(
+        dataInterval: number[],
+        dataExtent: number[],
+        handleEnds: number[],
+        forceState: ContinuousModel['stateList'][number]
+    ): BarVisual {
         var opts = {
             forceState: forceState,
             convertOpacityToAlpha: true
@@ -438,8 +437,8 @@ var ContinuousView = VisualMapView.extend({
         var colorStops = this._makeColorGradient(dataInterval, opts);
 
         var symbolSizes = [
-            this.getControllerVisual(dataInterval[0], 'symbolSize', opts),
-            this.getControllerVisual(dataInterval[1], 'symbolSize', opts)
+            this.getControllerVisual(dataInterval[0], 'symbolSize', opts) as number,
+            this.getControllerVisual(dataInterval[1], 'symbolSize', opts) as number
         ];
         var barPoints = this._createBarPoints(handleEnds, symbolSizes);
 
@@ -451,21 +450,24 @@ var ContinuousView = VisualMapView.extend({
                 colorStops[colorStops.length - 1].color
             ]
         };
-    },
+    }
 
-    /**
-     * @private
-     */
-    _makeColorGradient: function (dataInterval, opts) {
+    private _makeColorGradient(
+        dataInterval: number[],
+        opts: {
+            forceState?: ContinuousModel['stateList'][number]
+            convertOpacityToAlpha?: boolean
+        }
+    ) {
         // Considering colorHue, which is not linear, so we have to sample
         // to calculate gradient color stops, but not only caculate head
         // and tail.
         var sampleNumber = 100; // Arbitrary value.
-        var colorStops = [];
+        var colorStops: LinearGradientObject['colorStops'] = [];
         var step = (dataInterval[1] - dataInterval[0]) / sampleNumber;
 
         colorStops.push({
-            color: this.getControllerVisual(dataInterval[0], 'color', opts),
+            color: this.getControllerVisual(dataInterval[0], 'color', opts) as ColorString,
             offset: 0
         });
 
@@ -475,23 +477,20 @@ var ContinuousView = VisualMapView.extend({
                 break;
             }
             colorStops.push({
-                color: this.getControllerVisual(currValue, 'color', opts),
+                color: this.getControllerVisual(currValue, 'color', opts) as ColorString,
                 offset: i / sampleNumber
             });
         }
 
         colorStops.push({
-            color: this.getControllerVisual(dataInterval[1], 'color', opts),
+            color: this.getControllerVisual(dataInterval[1], 'color', opts) as ColorString,
             offset: 1
         });
 
         return colorStops;
-    },
+    }
 
-    /**
-     * @private
-     */
-    _createBarPoints: function (handleEnds, symbolSizes) {
+    private _createBarPoints(handleEnds: number[], symbolSizes: number[]) {
         var itemSize = this.visualMapModel.itemSize;
 
         return [
@@ -500,12 +499,9 @@ var ContinuousView = VisualMapView.extend({
             [itemSize[0], handleEnds[1]],
             [itemSize[0] - symbolSizes[1], handleEnds[1]]
         ];
-    },
+    }
 
-    /**
-     * @private
-     */
-    _createBarGroup: function (itemAlign) {
+    private _createBarGroup(itemAlign: helper.ItemAlign) {
         var orient = this._orient;
         var inverse = this.visualMapModel.get('inverse');
 
@@ -518,12 +514,9 @@ var ContinuousView = VisualMapView.extend({
             ? {scale: itemAlign === 'left' ? [1, -1] : [-1, -1]}
             : {scale: itemAlign === 'left' ? [1, 1] : [-1, 1]}
         );
-    },
+    }
 
-    /**
-     * @private
-     */
-    _updateHandle: function (handleEnds, visualInRange) {
+    private _updateHandle(handleEnds: number[], visualInRange: BarVisual) {
         if (!this._useHandle) {
             return;
         }
@@ -553,19 +546,17 @@ var ContinuousView = VisualMapView.extend({
                         ? (handleIndex === 0 ? 'bottom' : 'top')
                         : 'left',
                     shapes.barGroup
-                )
+                ) as TextAlign
             });
         }, this);
-    },
+    }
 
-    /**
-     * @private
-     * @param {number} cursorValue
-     * @param {number} textValue
-     * @param {string} [rangeSymbol]
-     * @param {number} [halfHoverLinkSize]
-     */
-    _showIndicator: function (cursorValue, textValue, rangeSymbol, halfHoverLinkSize) {
+    private _showIndicator(
+        cursorValue: number,
+        textValue: number,
+        rangeSymbol?: string,
+        halfHoverLinkSize?: number
+    ) {
         var visualMapModel = this.visualMapModel;
         var dataExtent = visualMapModel.getExtent();
         var itemSize = visualMapModel.itemSize;
@@ -600,17 +591,14 @@ var ContinuousView = VisualMapView.extend({
         var orient = this._orient;
         indicatorLabel.setStyle({
             text: (rangeSymbol ? rangeSymbol : '') + visualMapModel.formatValueText(textValue),
-            textVerticalAlign: orient === 'horizontal' ? align : 'middle',
-            textAlign: orient === 'horizontal' ? 'center' : align,
+            textVerticalAlign: orient === 'horizontal' ? align as TextVerticalAlign : 'middle',
+            textAlign: orient === 'horizontal' ? 'center' : align as TextAlign,
             x: textPoint[0],
             y: textPoint[1]
         });
-    },
+    }
 
-    /**
-     * @private
-     */
-    _enableHoverLinkToSeries: function () {
+    private _enableHoverLinkToSeries() {
         var self = this;
         this._shapes.barGroup
 
@@ -638,12 +626,9 @@ var ContinuousView = VisualMapView.extend({
                 self._hovering = false;
                 !self._dragging && self._clearHoverLinkToSeries();
             });
-    },
+    }
 
-    /**
-     * @private
-     */
-    _enableHoverLinkFromSeries: function () {
+    private _enableHoverLinkFromSeries() {
         var zr = this.api.getZr();
 
         if (this.visualMapModel.option.hoverLink) {
@@ -653,12 +638,9 @@ var ContinuousView = VisualMapView.extend({
         else {
             this._clearHoverLinkFromSeries();
         }
-    },
+    }
 
-    /**
-     * @private
-     */
-    _doHoverLinkToSeries: function (cursorPos, hoverOnBar) {
+    private _doHoverLinkToSeries(cursorPos: number, hoverOnBar?: boolean) {
         var visualMapModel = this.visualMapModel;
         var itemSize = visualMapModel.itemSize;
 
@@ -705,7 +687,7 @@ var ContinuousView = VisualMapView.extend({
         // handle, because the label on handle, which displays a exact value
         // but not range, might mislead users.
         var oldBatch = this._hoverLinkDataIndices;
-        var newBatch = [];
+        var newBatch: TargetDataIndices = [];
         if (hoverOnBar || useHoverLinkOnHandle(visualMapModel)) {
             newBatch = this._hoverLinkDataIndices = visualMapModel.findTargetDataIndices(valueRange);
         }
@@ -714,111 +696,105 @@ var ContinuousView = VisualMapView.extend({
 
         this._dispatchHighDown('downplay', helper.makeHighDownBatch(resultBatches[0], visualMapModel));
         this._dispatchHighDown('highlight', helper.makeHighDownBatch(resultBatches[1], visualMapModel));
-    },
+    }
 
-    /**
-     * @private
-     */
-    _hoverLinkFromSeriesMouseOver: function (e) {
+    private _hoverLinkFromSeriesMouseOver(e: ElementEvent) {
         var el = e.target;
         var visualMapModel = this.visualMapModel;
 
-        if (!el || el.dataIndex == null) {
+        if (!el || (el as ECElement).dataIndex == null) {
             return;
         }
 
-        var dataModel = this.ecModel.getSeriesByIndex(el.seriesIndex);
+        var dataModel = this.ecModel.getSeriesByIndex((el as ECElement).seriesIndex);
 
         if (!visualMapModel.isTargetSeries(dataModel)) {
             return;
         }
 
-        var data = dataModel.getData(el.dataType);
-        var value = data.get(visualMapModel.getDataDimension(data), el.dataIndex, true);
+        var data = dataModel.getData((el as ECElement).dataType);
+        var value = data.get(visualMapModel.getDataDimension(data), (el as ECElement).dataIndex) as number;
 
         if (!isNaN(value)) {
             this._showIndicator(value, value);
         }
-    },
+    }
 
-    /**
-     * @private
-     */
-    _hideIndicator: function () {
+    private _hideIndicator() {
         var shapes = this._shapes;
         shapes.indicator && shapes.indicator.attr('invisible', true);
         shapes.indicatorLabel && shapes.indicatorLabel.attr('invisible', true);
-    },
+    }
 
-    /**
-     * @private
-     */
-    _clearHoverLinkToSeries: function () {
+    private _clearHoverLinkToSeries() {
         this._hideIndicator();
 
         var indices = this._hoverLinkDataIndices;
         this._dispatchHighDown('downplay', helper.makeHighDownBatch(indices, this.visualMapModel));
 
         indices.length = 0;
-    },
+    }
 
-    /**
-     * @private
-     */
-    _clearHoverLinkFromSeries: function () {
+    private _clearHoverLinkFromSeries() {
         this._hideIndicator();
 
         var zr = this.api.getZr();
         zr.off('mouseover', this._hoverLinkFromSeriesMouseOver);
         zr.off('mouseout', this._hideIndicator);
-    },
-
-    /**
-     * @private
-     */
-    _applyTransform: function (vertex, element, inverse, global) {
+    }
+    private _applyTransform(vertex: number[], element: Element, inverse?: boolean, global?: boolean): number[]
+    private _applyTransform(vertex: Direction, element: Element, inverse?: boolean, global?: boolean): Direction
+    private _applyTransform(
+        vertex: number[] | Direction,
+        element: Element,
+        inverse?: boolean,
+        global?: boolean
+    ) {
         var transform = graphic.getTransform(element, global ? null : this.group);
 
-        return graphic[
-            zrUtil.isArray(vertex) ? 'applyTransform' : 'transformDirection'
-        ](vertex, transform, inverse);
-    },
+        return zrUtil.isArray(vertex)
+            ? graphic.applyTransform(vertex, transform, inverse)
+            : graphic.transformDirection(vertex, transform, inverse);
+    }
 
-    /**
-     * @private
-     */
-    _dispatchHighDown: function (type, batch) {
+ // TODO: TYPE more specified payload types.
+    private _dispatchHighDown(type: 'highlight' | 'downplay', batch: Payload['batch']) {
         batch && batch.length && this.api.dispatchAction({
             type: type,
             batch: batch
         });
-    },
+    }
 
     /**
      * @override
      */
-    dispose: function () {
+    dispose() {
         this._clearHoverLinkFromSeries();
         this._clearHoverLinkToSeries();
-    },
+    }
 
     /**
      * @override
      */
-    remove: function () {
+    remove() {
         this._clearHoverLinkFromSeries();
         this._clearHoverLinkToSeries();
     }
 
-});
+}
 
-function createPolygon(points, cursor, onDrift, onDragEnd) {
+function createPolygon(
+    points?: number[][],
+    cursor?: string,
+    onDrift?: (x: number, y: number) => void,
+    onDragEnd?: () => void
+) {
     return new graphic.Polygon({
         shape: {points: points},
         draggable: !!onDrift,
         cursor: cursor,
         drift: onDrift,
-        onmousemove: function (e) {
+        onmousemove(e) {
             // Fot mobile devicem, prevent screen slider on the button.
             eventTool.stop(e.event);
         },
@@ -826,13 +802,13 @@ function createPolygon(points, cursor, onDrift, onDragEnd) {
     });
 }
 
-function createHandlePoints(handleIndex, textSize) {
+function createHandlePoints(handleIndex: 0 | 1, textSize: number) {
     return handleIndex === 0
         ? [[0, 0], [textSize, 0], [textSize, -textSize]]
         : [[0, 0], [textSize, 0], [textSize, textSize]];
 }
 
-function createIndicatorPoints(isRange, halfHoverLinkSize, pos, extentMax) {
+function createIndicatorPoints(isRange: boolean, halfHoverLinkSize: number, pos: number, extentMax: number) {
     return isRange
         ? [ // indicate range
             [0, -mathMin(halfHoverLinkSize, mathMax(pos, 0))],
@@ -844,7 +820,7 @@ function createIndicatorPoints(isRange, halfHoverLinkSize, pos, extentMax) {
         ];
 }
 
-function getHalfHoverLinkSize(visualMapModel, dataExtent, sizeExtent) {
+function getHalfHoverLinkSize(visualMapModel: ContinuousModel, dataExtent: number[], sizeExtent: number[]) {
     var halfHoverLinkSize = HOVER_LINK_SIZE / 2;
     var hoverLinkDataSize = visualMapModel.get('hoverLinkDataSize');
     if (hoverLinkDataSize) {
@@ -853,13 +829,15 @@ function getHalfHoverLinkSize(visualMapModel, dataExtent, sizeExtent) {
     return halfHoverLinkSize;
 }
 
-function useHoverLinkOnHandle(visualMapModel) {
+function useHoverLinkOnHandle(visualMapModel: ContinuousModel) {
     var hoverLinkOnHandle = visualMapModel.get('hoverLinkOnHandle');
     return !!(hoverLinkOnHandle == null ? visualMapModel.get('realtime') : hoverLinkOnHandle);
 }
 
-function getCursor(orient) {
+function getCursor(orient: Orient) {
     return orient === 'vertical' ? 'ns-resize' : 'ew-resize';
 }
 
+ComponentView.registerClass(ContinuousView);
+
 export default ContinuousView;
\ No newline at end of file
diff --git a/src/component/visualMap/PiecewiseModel.ts b/src/component/visualMap/PiecewiseModel.ts
index bcd547e..a156c86 100644
--- a/src/component/visualMap/PiecewiseModel.ts
+++ b/src/component/visualMap/PiecewiseModel.ts
@@ -25,6 +25,7 @@ import visualDefault from '../../visual/visualDefault';
 import {reformIntervals} from '../../util/number';
 import { VisualOptionPiecewise, BuiltinVisualProperty } from '../../util/types';
 import { Dictionary } from 'zrender/src/core/types';
+import ComponentModel from '../../model/Component';
 
 
 interface VisualPiece extends VisualOptionPiecewise {
@@ -212,7 +213,7 @@ class PiecewiseModel extends VisualMapModel<PiecewiseVisualMapOption> {
         super.completeVisualOption.apply(this, arguments as any);
     }
 
-    _resetSelected(newOption: PiecewiseVisualMapOption, isInit?: boolean) {
+    private _resetSelected(newOption: PiecewiseVisualMapOption, isInit?: boolean) {
         var thisOption = this.option;
         var pieceList = this._pieceList;
 
@@ -260,10 +261,9 @@ class PiecewiseModel extends VisualMapModel<PiecewiseVisualMapOption> {
     }
 
     /**
-     * @private
      * @return {string}
      */
-    _determineMode() {
+    private _determineMode() {
         var option = this.option;
 
         return option.pieces && option.pieces.length > 0
@@ -274,7 +274,6 @@ class PiecewiseModel extends VisualMapModel<PiecewiseVisualMapOption> {
     }
 
     /**
-     * @public
      * @override
      */
     setSelected(selected: this['option']['selected']) {
@@ -282,7 +281,6 @@ class PiecewiseModel extends VisualMapModel<PiecewiseVisualMapOption> {
     }
 
     /**
-     * @public
      * @override
      */
     getValueState(value: number): VisualState {
@@ -297,8 +295,7 @@ class PiecewiseModel extends VisualMapModel<PiecewiseVisualMapOption> {
 
     /**
      * @public
-     * @params {number} pieceIndex piece index in visualMapModel.getPieceList()
-     * @return {Array.<Object>} [{seriesId, dataIndex: <Array.<number>>}, ...]
+     * @param pieceIndex piece index in visualMapModel.getPieceList()
      */
     findTargetDataIndices(pieceIndex: number) {
         type DataIndices = {
@@ -330,7 +327,7 @@ class PiecewiseModel extends VisualMapModel<PiecewiseVisualMapOption> {
      * @param piece piece.value or piece.interval is required.
      * @return  Can be Infinity or -Infinity
      */
-    getRepresentValue<T extends InnerVisualPiece>(piece: T) {
+    getRepresentValue(piece: InnerVisualPiece) {
         var representValue;
         if (this.isCategory()) {
             representValue = piece.value;
@@ -346,8 +343,8 @@ class PiecewiseModel extends VisualMapModel<PiecewiseVisualMapOption> {
                     : (pieceInterval[0] + pieceInterval[1]) / 2;
             }
         }
-        //
-        return representValue as GetPieceValueType<T>;
+
+        return representValue;
     }
 
     getVisualMeta(
@@ -365,7 +362,7 @@ class PiecewiseModel extends VisualMapModel<PiecewiseVisualMapOption> {
         function setStop(interval: [number, number], valueState?: VisualState) {
             var representValue = visualMapModel.getRepresentValue({
                 interval: interval
-            });// Not category
+            }) as number;// Not category
             if (!valueState) {
                 valueState = visualMapModel.getValueState(representValue);
             }
@@ -411,7 +408,9 @@ class PiecewiseModel extends VisualMapModel<PiecewiseVisualMapOption> {
     }
 
 
-    static defaultOption: PiecewiseVisualMapOption = {
+    static defaultOption = zrUtil.merge(
+        zrUtil.clone(VisualMapModel.defaultOption),
+    {
         selected: null,
         minOpen: false,             // Whether include values that smaller than `min`.
         maxOpen: false,             // Whether include values that bigger than `max`.
@@ -428,7 +427,7 @@ class PiecewiseModel extends VisualMapModel<PiecewiseVisualMapOption> {
         selectedMode: 'multiple',   // Can be 'multiple' or 'single'.
         itemGap: 10,                // The gap between two items, in px.
         hoverLink: true             // Enable hover highlight.
-    }
+    }) as PiecewiseVisualMapOption
 
 };
 
@@ -598,4 +597,6 @@ function normalizeReverse(thisOption: PiecewiseVisualMapOption, pieceList: Inner
     }
 }
 
+ComponentModel.registerClass(PiecewiseModel);
+
 export default PiecewiseModel;
\ No newline at end of file
diff --git a/src/component/visualMap/PiecewiseView.ts b/src/component/visualMap/PiecewiseView.ts
index de31858..1bc7757 100644
--- a/src/component/visualMap/PiecewiseView.ts
+++ b/src/component/visualMap/PiecewiseView.ts
@@ -17,24 +17,26 @@
 * under the License.
 */
 
-// @ts-nocheck
-
 import * as zrUtil from 'zrender/src/core/util';
 import VisualMapView from './VisualMapView';
 import * as graphic from '../../util/graphic';
 import {createSymbol} from '../../util/symbol';
 import * as layout from '../../util/layout';
 import * as helper from './helper';
+import PiecewiseModel from './PiecewiseModel';
+import ComponentView from '../../view/Component';
+import { TextAlign } from 'zrender/src/core/types';
+import { VisualMappingOption } from '../../visual/VisualMapping';
 
-var PiecewiseVisualMapView = VisualMapView.extend({
+class PiecewiseVisualMapView extends VisualMapView {
 
-    type: 'visualMap.piecewise',
+    static type = 'visualMap.piecewise' as const
 
-    /**
-     * @protected
-     * @override
-     */
-    doRender: function () {
+    type = PiecewiseVisualMapView.type
+
+    visualMapModel: PiecewiseModel
+
+    protected doRender() {
         var thisGroup = this.group;
 
         thisGroup.removeAll();
@@ -68,7 +70,7 @@ var PiecewiseVisualMapView = VisualMapView.extend({
 
         this.positionGroup(thisGroup);
 
-        function renderItem(item) {
+        function renderItem(this: PiecewiseVisualMapView, item: typeof viewData.viewPieceList[number]) {
             var piece = item.piece;
 
             var itemGroup = new graphic.Group();
@@ -76,7 +78,8 @@ var PiecewiseVisualMapView = VisualMapView.extend({
 
             this._enableHoverLink(itemGroup, item.indexInModelPieceList);
 
-            var representValue = visualMapModel.getRepresentValue(piece);
+            // TODO Category
+            var representValue = visualMapModel.getRepresentValue(piece) as number;
 
             this._createItemSymbol(
                 itemGroup, representValue, [0, 0, itemSize[0], itemSize[1]]
@@ -91,7 +94,7 @@ var PiecewiseVisualMapView = VisualMapView.extend({
                         y: itemSize[1] / 2,
                         text: piece.text,
                         textVerticalAlign: 'middle',
-                        textAlign: itemAlign,
+                        textAlign: itemAlign as TextAlign,
                         textFont: textFont,
                         textFill: textFill,
                         opacity: visualState === 'outOfRange' ? 0.5 : 1
@@ -101,19 +104,17 @@ var PiecewiseVisualMapView = VisualMapView.extend({
 
             thisGroup.add(itemGroup);
         }
-    },
+    }
 
-    /**
-     * @private
-     */
-    _enableHoverLink: function (itemGroup, pieceIndex) {
+    private _enableHoverLink(itemGroup: graphic.Group, pieceIndex: number) {
         itemGroup
             .on('mouseover', zrUtil.bind(onHoverLink, this, 'highlight'))
             .on('mouseout', zrUtil.bind(onHoverLink, this, 'downplay'));
 
-        function onHoverLink(method) {
+        function onHoverLink(this: PiecewiseVisualMapView, method?: 'highlight' | 'downplay') {
             var visualMapModel = this.visualMapModel;
 
+            // TODO: TYPE More detailed action types
             visualMapModel.option.hoverLink && this.api.dispatchAction({
                 type: method,
                 batch: helper.makeHighDownBatch(
@@ -122,12 +123,9 @@ var PiecewiseVisualMapView = VisualMapView.extend({
                 )
             });
         }
-    },
+    }
 
-    /**
-     * @private
-     */
-    _getItemAlign: function () {
+    private _getItemAlign(): helper.ItemAlign {
         var visualMapModel = this.visualMapModel;
         var modelOption = visualMapModel.option;
 
@@ -143,12 +141,15 @@ var PiecewiseVisualMapView = VisualMapView.extend({
             }
             return align;
         }
-    },
+    }
 
-    /**
-     * @private
-     */
-    _renderEndsText: function (group, text, itemSize, showLabel, itemAlign) {
+    private _renderEndsText(
+        group: graphic.Group,
+        text: string,
+        itemSize: number[],
+        showLabel: boolean,
+        itemAlign: helper.ItemAlign
+    ) {
         if (!text) {
             return;
         }
@@ -161,7 +162,7 @@ var PiecewiseVisualMapView = VisualMapView.extend({
                 x: showLabel ? (itemAlign === 'right' ? itemSize[0] : 0) : itemSize[0] / 2,
                 y: itemSize[1] / 2,
                 textVerticalAlign: 'middle',
-                textAlign: showLabel ? itemAlign : 'center',
+                textAlign: showLabel ? (itemAlign as TextAlign) : 'center',
                 text: text,
                 textFont: textStyleModel.getFont(),
                 textFill: textStyleModel.getTextColor()
@@ -169,13 +170,13 @@ var PiecewiseVisualMapView = VisualMapView.extend({
         }));
 
         group.add(itemGroup);
-    },
+    }
 
     /**
      * @private
      * @return {Object} {peiceList, endsText} The order is the same as screen pixel order.
      */
-    _getViewData: function () {
+    private _getViewData() {
         var visualMapModel = this.visualMapModel;
 
         var viewPieceList = zrUtil.map(visualMapModel.getPieceList(), function (piece, index) {
@@ -197,23 +198,25 @@ var PiecewiseVisualMapView = VisualMapView.extend({
         }
 
         return {viewPieceList: viewPieceList, endsText: endsText};
-    },
+    }
 
-    /**
-     * @private
-     */
-    _createItemSymbol: function (group, representValue, shapeParam) {
+    private _createItemSymbol(
+        group: graphic.Group,
+        representValue: number,
+        shapeParam: number[]
+    ) {
         group.add(createSymbol(
-            this.getControllerVisual(representValue, 'symbol'),
+            // symbol will be string
+            this.getControllerVisual(representValue, 'symbol') as string,
             shapeParam[0], shapeParam[1], shapeParam[2], shapeParam[3],
-            this.getControllerVisual(representValue, 'color')
+            // color will be string
+            this.getControllerVisual(representValue, 'color') as string
         ));
-    },
+    }
 
-    /**
-     * @private
-     */
-    _onItemClick: function (piece) {
+    private _onItemClick(
+        piece: VisualMappingOption['pieceList'][number]
+    ) {
         var visualMapModel = this.visualMapModel;
         var option = visualMapModel.option;
         var selected = zrUtil.clone(option.selected);
@@ -236,6 +239,8 @@ var PiecewiseVisualMapView = VisualMapView.extend({
             selected: selected
         });
     }
-});
+}
+
+ComponentView.registerClass(PiecewiseVisualMapView);
 
 export default PiecewiseVisualMapView;
\ No newline at end of file
diff --git a/src/component/visualMap/VisualMapModel.ts b/src/component/visualMap/VisualMapModel.ts
index b3594a5..c2a9eb7 100644
--- a/src/component/visualMap/VisualMapModel.ts
+++ b/src/component/visualMap/VisualMapModel.ts
@@ -179,7 +179,7 @@ class VisualMapModel<Opts extends VisualMapOption = VisualMapOption> extends Com
 
     targetVisuals = {}
 
-    controllerVisuals = {}
+    controllerVisuals = {} as ReturnType<typeof visualSolution.createVisualMappings>
 
     textStyleModel: Model<LabelOption>
 
@@ -393,7 +393,10 @@ class VisualMapModel<Opts extends VisualMapOption = VisualMapOption> extends Com
 
         var ecModel = this.ecModel;
         var thisOption = this.option;
-        var base = {inRange: thisOption.inRange, outOfRange: thisOption.outOfRange};
+        var base = {
+            inRange: thisOption.inRange,
+            outOfRange: thisOption.outOfRange
+        };
 
         var target = thisOption.target || (thisOption.target = {});
         var controller = thisOption.controller || (thisOption.controller = {});
@@ -409,7 +412,7 @@ class VisualMapModel<Opts extends VisualMapOption = VisualMapOption> extends Com
         // completeInactive.call(this, target, 'outOfRange', 'inRange');
         completeController.call(this, controller);
 
-        function completeSingle(this: VisualMapModel, base?: VisualMapOption['target']) {
+        function completeSingle(this: VisualMapModel, base: VisualMapOption['target']) {
             // Compatible with ec2 dataRange.color.
             // The mapping order of dataRange.color is: [high value, ..., low value]
             // whereas inRange.color and outOfRange.color is [low value, ..., high value]
@@ -570,7 +573,7 @@ class VisualMapModel<Opts extends VisualMapOption = VisualMapOption> extends Com
     }
 
 
-    defaultOption: VisualMapOption = {
+    static defaultOption: VisualMapOption = {
         show: true,
 
         zlevel: 0,
diff --git a/src/component/visualMap/VisualMapView.ts b/src/component/visualMap/VisualMapView.ts
index 17273df..ea29e68 100644
--- a/src/component/visualMap/VisualMapView.ts
+++ b/src/component/visualMap/VisualMapView.ts
@@ -17,49 +17,46 @@
 * under the License.
 */
 
-// @ts-nocheck
-
-import * as echarts from '../../echarts';
 import * as zrUtil from 'zrender/src/core/util';
-import * as graphic from '../../util/graphic';
+import {Group, Rect} from '../../util/graphic';
 import * as formatUtil from '../../util/format';
 import * as layout from '../../util/layout';
 import VisualMapping from '../../visual/VisualMapping';
+import ComponentView from '../../view/Component';
+import GlobalModel from '../../model/Global';
+import ExtensionAPI from '../../ExtensionAPI';
+import VisualMapModel from './VisualMapModel';
+import { VisualOptionUnit, ColorString } from '../../util/types';
+import PiecewiseModel from './PiecewiseModel';
 
-export default echarts.extendComponentView({
+type VisualState = VisualMapModel['stateList'][number]
 
-    type: 'visualMap',
+class VisualMapView extends ComponentView {
+    static type = 'visualMap'
+    type = VisualMapView.type
 
-    /**
-     * @readOnly
-     * @type {Object}
-     */
-    autoPositionValues: {left: 1, right: 1, top: 1, bottom: 1},
+    autoPositionValues = {left: 1, right: 1, top: 1, bottom: 1} as const
 
-    init: function (ecModel, api) {
-        /**
-         * @readOnly
-         * @type {module:echarts/model/Global}
-         */
-        this.ecModel = ecModel;
+    ecModel: GlobalModel
 
-        /**
-         * @readOnly
-         * @type {module:echarts/ExtensionAPI}
-         */
-        this.api = api;
+    api: ExtensionAPI
 
-        /**
-         * @readOnly
-         * @type {module:echarts/component/visualMap/visualMapModel}
-         */
-        this.visualMapModel;
-    },
+    visualMapModel: VisualMapModel
+
+    init(ecModel: GlobalModel, api: ExtensionAPI) {
+        this.ecModel = ecModel;
+        this.api = api;
+    }
 
     /**
      * @protected
      */
-    render: function (visualMapModel, ecModel, api, payload) {
+    render(
+        visualMapModel: VisualMapModel,
+        ecModel: GlobalModel,
+        api: ExtensionAPI,
+        payload: unknown    // TODO: TYPE
+    ) {
         this.visualMapModel = visualMapModel;
 
         if (visualMapModel.get('show') === false) {
@@ -67,18 +64,18 @@ export default echarts.extendComponentView({
             return;
         }
 
-        this.doRender.apply(this, arguments);
-    },
+        this.doRender(visualMapModel, ecModel, api, payload);
+    }
 
     /**
      * @protected
      */
-    renderBackground: function (group) {
+    renderBackground(group: Group) {
         var visualMapModel = this.visualMapModel;
         var padding = formatUtil.normalizeCssArray(visualMapModel.get('padding') || 0);
         var rect = group.getBoundingRect();
 
-        group.add(new graphic.Rect({
+        group.add(new Rect({
             z2: -1, // Lay background rect on the lowest layer.
             silent: true,
             shape: {
@@ -93,39 +90,47 @@ export default echarts.extendComponentView({
                 lineWidth: visualMapModel.get('borderWidth')
             }
         }));
-    },
+    }
 
     /**
      * @protected
-     * @param {number} targetValue can be Infinity or -Infinity
-     * @param {string=} visualCluster Only can be 'color' 'opacity' 'symbol' 'symbolSize'
-     * @param {Object} [opts]
-     * @param {string=} [opts.forceState] Specify state, instead of using getValueState method.
-     * @param {string=} [opts.convertOpacityToAlpha=false] For color gradient in controller widget.
+     * @param targetValue can be Infinity or -Infinity
+     * @param visualCluster Only can be 'color' 'opacity' 'symbol' 'symbolSize'
+     * @param opts
+     * @param opts.forceState Specify state, instead of using getValueState method.
+     * @param opts.convertOpacityToAlpha For color gradient in controller widget.
      * @return {*} Visual value.
      */
-    getControllerVisual: function (targetValue, visualCluster, opts) {
+    protected getControllerVisual(
+        targetValue: number,
+        visualCluster: 'color' | 'opacity' | 'symbol' | 'symbolSize',
+        opts?: {
+            forceState?: VisualState
+            convertOpacityToAlpha?: boolean
+        }
+    ) {
+
         opts = opts || {};
 
         var forceState = opts.forceState;
         var visualMapModel = this.visualMapModel;
-        var visualObj = {};
+        var visualObj: {[key in typeof visualCluster]?: VisualOptionUnit[key]} = {};
 
         // Default values.
         if (visualCluster === 'symbol') {
-            visualObj.symbol = visualMapModel.get('itemSymbol');
+            visualObj.symbol = (visualMapModel as PiecewiseModel).get('itemSymbol');
         }
         if (visualCluster === 'color') {
             var defaultColor = visualMapModel.get('contentColor');
-            visualObj.color = defaultColor;
+            visualObj.color = defaultColor as ColorString;
         }
 
-        function getter(key) {
+        function getter(key: typeof visualCluster) {
             return visualObj[key];
         }
 
-        function setter(key, value) {
-            visualObj[key] = value;
+        function setter(key: typeof visualCluster, value: any) {
+            (visualObj as any)[key] = value;
         }
 
         var mappings = visualMapModel.controllerVisuals[
@@ -147,12 +152,9 @@ export default echarts.extendComponentView({
         });
 
         return visualObj[visualCluster];
-    },
+    }
 
-    /**
-     * @protected
-     */
-    positionGroup: function (group) {
+    protected positionGroup(group: Group) {
         var model = this.visualMapModel;
         var api = this.api;
 
@@ -161,12 +163,16 @@ export default echarts.extendComponentView({
             model.getBoxLayoutParams(),
             {width: api.getWidth(), height: api.getHeight()}
         );
-    },
+    }
 
-    /**
-     * @protected
-     * @abstract
-     */
-    doRender: zrUtil.noop
+    protected doRender(
+        visualMapModel: VisualMapModel,
+        ecModel: GlobalModel,
+        api: ExtensionAPI,
+        payload: unknown
+    ) {}
+}
+
+ComponentView.registerClass(VisualMapView);
 
-});
+export default VisualMapView;
\ No newline at end of file
diff --git a/src/component/visualMap/helper.ts b/src/component/visualMap/helper.ts
index e3bb71b..3910653 100644
--- a/src/component/visualMap/helper.ts
+++ b/src/component/visualMap/helper.ts
@@ -27,7 +27,9 @@ const paramsSet = [
     ['left', 'right', 'width'],
     ['top', 'bottom', 'height']
 ] as const;
-type LayoutKey = (typeof paramsSet)[number][number];
+export type ItemHorizontalAlign = typeof paramsSet[0][number];
+export type ItemVerticalAlign = typeof paramsSet[1][number];
+export type ItemAlign = ItemVerticalAlign | ItemHorizontalAlign;
 
 /**
  * @param visualMapModel
@@ -39,12 +41,12 @@ export function getItemAlign(
     visualMapModel: VisualMapModel,
     api: ExtensionAPI,
     itemSize: number[]
-) {
+): ItemAlign {
     var modelOption = visualMapModel.option;
     var itemAlign = modelOption.align;
 
     if (itemAlign != null && itemAlign !== 'auto') {
-        return itemAlign;
+        return itemAlign as ItemAlign;
     }
 
     // Auto decision align.
@@ -55,7 +57,7 @@ export function getItemAlign(
     var fakeValue = [0, null, 10];
 
     var layoutInput = {} as {
-        [key in LayoutKey]: number | string
+        [key in ItemAlign]: number | string
     };
     for (var i = 0; i < 3; i++) {
         layoutInput[paramsSet[1 - realIndex][i]] = fakeValue[i];
@@ -75,6 +77,8 @@ export function getItemAlign(
  * Prepare dataIndex for outside usage, where dataIndex means rawIndex, and
  * dataIndexInside means filtered index.
  */
+
+ // TODO: TYPE more specified payload types.
 export function makeHighDownBatch(batch: Payload['batch'], visualMapModel: VisualMapModel): Payload['batch'] {
     zrUtil.each(batch || [], function (batchItem) {
         if (batchItem.dataIndex != null) {
diff --git a/src/component/visualMap/preprocessor.ts b/src/component/visualMap/preprocessor.ts
index 9992ce1..b2b24ba 100644
--- a/src/component/visualMap/preprocessor.ts
+++ b/src/component/visualMap/preprocessor.ts
@@ -18,7 +18,6 @@
 */
 
 // @ts-nocheck
-
 import * as zrUtil from 'zrender/src/core/util';
 
 var each = zrUtil.each;
@@ -57,6 +56,6 @@ export default function (option) {
     });
 }
 
-function has(obj, name) {
+function has(obj: object, name: string) {
     return obj && obj.hasOwnProperty && obj.hasOwnProperty(name);
 }
diff --git a/src/coord/axisModelCreator.ts b/src/coord/axisModelCreator.ts
index 1d3ec6f..978394c 100644
--- a/src/coord/axisModelCreator.ts
+++ b/src/coord/axisModelCreator.ts
@@ -24,7 +24,8 @@ import axisDefault from './axisDefault';
 import ComponentModel from '../model/Component';
 import {
     getLayoutParams,
-    mergeLayoutParam
+    mergeLayoutParam,
+    fetchLayoutMode
 } from '../util/layout';
 import OrdinalMeta from '../data/OrdinalMeta';
 import { DimensionName, ComponentOption } from '../util/types';
diff --git a/src/data/OrdinalMeta.ts b/src/data/OrdinalMeta.ts
index a387ce9..415d4e8 100644
--- a/src/data/OrdinalMeta.ts
+++ b/src/data/OrdinalMeta.ts
@@ -57,6 +57,7 @@ class OrdinalMeta {
     };
 
     getOrdinal(category: OrdinalRawValue): OrdinalNumber {
+        // @ts-ignore
         return this._getOrCreateMap().get(category);
     }
 
@@ -91,12 +92,14 @@ class OrdinalMeta {
         }
 
         var map = this._getOrCreateMap();
+        // @ts-ignore
         index = map.get(category);
 
         if (index == null) {
             if (needCollect) {
                 index = this.categories.length;
                 this.categories[index] = category;
+                // @ts-ignore
                 map.set(category, index);
             }
             else {
diff --git a/src/export.ts b/src/export.ts
index 8313fc8..8842264 100644
--- a/src/export.ts
+++ b/src/export.ts
@@ -63,33 +63,35 @@ zrUtil.each(
 );
 export {ecUtil as util};
 
-var graphic = {};
+const GRAPHIC_KEYS = [
+    'extendShape', 'extendPath', 'makePath', 'makeImage',
+    'mergePath', 'resizePath', 'createIcon',
+    'setHoverStyle', 'setLabelStyle', 'setTextStyle', 'setText',
+    'getFont', 'updateProps', 'initProps', 'getTransform',
+    'clipPointsByRect', 'clipRectByRect',
+    'registerShape', 'getShapeClass',
+    'Group',
+    'Image',
+    'Text',
+    'Circle',
+    'Sector',
+    'Ring',
+    'Polygon',
+    'Polyline',
+    'Rect',
+    'Line',
+    'BezierCurve',
+    'Arc',
+    'IncrementalDisplayable',
+    'CompoundPath',
+    'LinearGradient',
+    'RadialGradient',
+    'BoundingRect'
+] as const;
+
+var graphic = {} as {[key in typeof GRAPHIC_KEYS[number]]: any};
 zrUtil.each(
-    [
-        'extendShape', 'extendPath', 'makePath', 'makeImage',
-        'mergePath', 'resizePath', 'createIcon',
-        'setHoverStyle', 'setLabelStyle', 'setTextStyle', 'setText',
-        'getFont', 'updateProps', 'initProps', 'getTransform',
-        'clipPointsByRect', 'clipRectByRect',
-        'registerShape', 'getShapeClass',
-        'Group',
-        'Image',
-        'Text',
-        'Circle',
-        'Sector',
-        'Ring',
-        'Polygon',
-        'Polyline',
-        'Rect',
-        'Line',
-        'BezierCurve',
-        'Arc',
-        'IncrementalDisplayable',
-        'CompoundPath',
-        'LinearGradient',
-        'RadialGradient',
-        'BoundingRect'
-    ],
+    GRAPHIC_KEYS,
     function (name) {
         (graphic as any)[name] = (graphicUtil as any)[name];
     }
diff --git a/src/util/graphic.ts b/src/util/graphic.ts
index 7e18431..70b6439 100644
--- a/src/util/graphic.ts
+++ b/src/util/graphic.ts
@@ -50,7 +50,7 @@ import { PatternObject } from 'zrender/src/graphic/Pattern';
 import { GradientObject } from 'zrender/src/graphic/Gradient';
 import Element, { ElementEvent } from 'zrender/src/Element';
 import Model from '../model/Model';
-import { AnimationOptionMixin, LabelOption, AnimationDelayCallbackParam, DisplayState } from './types';
+import { AnimationOptionMixin, LabelOption, AnimationDelayCallbackParam, DisplayState, ECElement } from './types';
 import GlobalModel from '../model/Global';
 
 
@@ -1373,7 +1373,7 @@ export function groupTransition(
             if (oldEl) {
                 var newProp = getAnimatableProps(el);
                 el.attr(getAnimatableProps(oldEl));
-                updateProps(el, newProp, animatableModel, el.dataIndex);
+                updateProps(el, newProp, animatableModel, (el as ECElement).dataIndex);
             }
         }
     });
diff --git a/src/util/layout.ts b/src/util/layout.ts
index 8f8c8b0..714b2c0 100644
--- a/src/util/layout.ts
+++ b/src/util/layout.ts
@@ -334,9 +334,9 @@ export function getLayoutRect(
 export function positionElement(
     el: Element,
     positionInfo: BoxLayoutOptionMixin,
-    containerRect: RectLike,
-    margin: number[] | number,
-    opt: {
+    containerRect: {width: number, height: number},
+    margin?: number[] | number,
+    opt?: {
         hv: [1 | 0, 1 | 0],
         boundingMode: 'all' | 'raw'
     }
diff --git a/src/util/model.ts b/src/util/model.ts
index 86efb30..3a3b45d 100644
--- a/src/util/model.ts
+++ b/src/util/model.ts
@@ -17,7 +17,18 @@
 * under the License.
 */
 
-import * as zrUtil from 'zrender/src/core/util';
+import {
+    each,
+    isObject,
+    isArray,
+    merge,
+    createHashMap,
+    HashMap,
+    map,
+    assert,
+    isString,
+    indexOf
+} from 'zrender/src/core/util';
 import env from 'zrender/src/core/env';
 import GlobalModel, { QueryConditionKindB } from '../model/Global';
 import ComponentModel from '../model/Component';
@@ -37,10 +48,6 @@ import SeriesModel from '../model/Series';
 import AxisModel from '../coord/cartesian/AxisModel';
 import GridModel from '../coord/cartesian/GridModel';
 
-var each = zrUtil.each;
-var isObject = zrUtil.isObject;
-var isArray = zrUtil.isArray;
-
 /**
  * Make the name displayable. But we should
  * make sure it is not duplicated with user
@@ -170,7 +177,7 @@ export function mappingToExists<T extends MappingExistItem>(
     // update partial option but not be expected to change order.
     newCptOptions = (newCptOptions || []).slice();
 
-    var result: MappingResultItem<T>[] = zrUtil.map(exists || [], function (obj, index) {
+    var result: MappingResultItem<T>[] = map(exists || [], function (obj, index) {
         return {exist: obj};
     });
 
@@ -263,7 +270,7 @@ export function makeIdAndName(
     // to specify multi components (like series) by one name.
 
     // Ensure that each id is distinct.
-    var idMap = zrUtil.createHashMap();
+    var idMap = createHashMap();
 
     each(mapResult, function (item, index) {
         var existCpt = item.exist;
@@ -273,7 +280,7 @@ export function makeIdAndName(
     each(mapResult, function (item, index) {
         var opt = item.option;
 
-        zrUtil.assert(
+        assert(
             !opt || opt.id == null || !idMap.get(opt.id) || idMap.get(opt.id) === item,
             'id duplicates: ' + (opt && opt.id)
         );
@@ -345,7 +352,7 @@ export function isIdInner(cptOption: ComponentOption): boolean {
 }
 
 type BatchItem = {
-    seriesId: number,
+    seriesId: string,
     dataIndex: number[]
 };
 /**
@@ -420,15 +427,15 @@ export function queryDataIndex(data: List, payload: Payload): number | number[]
         return payload.dataIndexInside;
     }
     else if (payload.dataIndex != null) {
-        return zrUtil.isArray(payload.dataIndex)
-            ? zrUtil.map(payload.dataIndex, function (value) {
+        return isArray(payload.dataIndex)
+            ? map(payload.dataIndex, function (value) {
                 return data.indexOfRawIndex(value);
             })
             : data.indexOfRawIndex(payload.dataIndex);
     }
     else if (payload.name != null) {
-        return zrUtil.isArray(payload.name)
-            ? zrUtil.map(payload.name, function (value) {
+        return isArray(payload.name)
+            ? map(payload.name, function (value) {
                 return data.indexOfName(value);
             })
             : data.indexOfName(payload.name);
@@ -552,7 +559,7 @@ export function parseFinder(
     opt?: {defaultMainType?: string, includeMainTypes?: string[]}
 ): ParsedModelFinder {
     var finder: ModelFinderObject;
-    if (zrUtil.isString(finderInput)) {
+    if (isString(finderInput)) {
         var obj = {};
         (obj as any)[finderInput + 'Index'] = 0;
         finder = obj;
@@ -589,7 +596,7 @@ export function parseFinder(
             || !queryType
             || value == null
             || (queryType === 'index' && value === 'none')
-            || (opt && opt.includeMainTypes && zrUtil.indexOf(opt.includeMainTypes, mainType) < 0)
+            || (opt && opt.includeMainTypes && indexOf(opt.includeMainTypes, mainType) < 0)
         ) {
             return;
         }
@@ -641,12 +648,12 @@ export function groupData<T>(
     getKey: (item: T) => string // return key
 ): {
     keys: string[],
-    buckets: zrUtil.HashMap<T[]> // hasmap key: the key returned by `getKey`.
+    buckets: HashMap<T[]> // hasmap key: the key returned by `getKey`.
 } {
-    var buckets = zrUtil.createHashMap<T[]>();
+    var buckets = createHashMap<T[]>();
     var keys = [] as string[];
 
-    zrUtil.each(array, function (item) {
+    each(array, function (item) {
         var key = getKey(item);
         (buckets.get(key)
             || (keys.push(key), buckets.set(key, []))
@@ -658,5 +665,5 @@ export function groupData<T>(
 
 export function mergeOption<T, K>(option1: T, option2: K): T & K {
     // See also `model/Component.ts#getDefaultOption`
-    return zrUtil.merge(zrUtil.merge({}, option1, true), option2, true);
+    return merge(merge({}, option1, true), option2, true);
 }
diff --git a/src/util/number.ts b/src/util/number.ts
index 6d16208..eacc8ff 100644
--- a/src/util/number.ts
+++ b/src/util/number.ts
@@ -43,8 +43,8 @@ function _trim(str: string): string {
  */
 export function linearMap(
     val: number,
-    domain: [number, number],
-    range: [number, number],
+    domain: number[],
+    range: number[],
     clamp?: boolean
 ): number {
     var subDomain = domain[1] - domain[0];
diff --git a/src/util/types.ts b/src/util/types.ts
index aabdead..05f16a9 100644
--- a/src/util/types.ts
+++ b/src/util/types.ts
@@ -35,11 +35,12 @@ import { createHashMap, HashMap } from 'zrender/src/core/util';
 import { TaskPlanCallbackReturn, TaskProgressParams } from '../stream/task';
 import List, {ListDimensionType} from '../data/List';
 import { Dictionary, ImageLike } from 'zrender/src/core/types';
-import { GradientObject } from 'zrender/src/graphic/Gradient';
 import { PatternObject } from 'zrender/src/graphic/Pattern';
 import Source from '../data/Source';
 import { TooltipMarker } from './format';
 import { easingType } from 'zrender/src/animation/easing';
+import { LinearGradientObject } from 'zrender/src/graphic/LinearGradient';
+import { RadialGradientObject } from 'zrender/src/graphic/RadialGradient';
 
 
 
@@ -50,7 +51,7 @@ import { easingType } from 'zrender/src/animation/easing';
 export type RendererType = 'canvas' | 'svg';
 
 export type ColorString = string;
-export type ZRColor = ColorString | GradientObject | PatternObject
+export type ZRColor = ColorString | LinearGradientObject | RadialGradientObject | PatternObject
 export type ZRLineType = 'solid' | 'dotted'
 export type ZRAlign = 'left' | 'center' | 'right'
 export type ZRVerticalAlign = 'top' | 'middle' | 'bottom'
@@ -655,7 +656,6 @@ export type VisualOptionLinear = Arrayable<VisualOptionUnit>
  */
 export type VisualOptionCategory = Arrayable<VisualOptionUnit> | Dictionaryable<VisualOptionUnit>
 
-export type VisualOption = VisualOptionFixed | VisualOptionLinear | VisualOptionCategory | VisualOptionPiecewise
 /**
  * All visual properties can be encoded.
  */
diff --git a/src/view/Component.ts b/src/view/Component.ts
index f0b3d1e..f695505 100644
--- a/src/view/Component.ts
+++ b/src/view/Component.ts
@@ -26,7 +26,7 @@ import ExtensionAPI from '../ExtensionAPI';
 import {Payload, ViewRootGroup, ECEvent, EventQueryItem} from '../util/types';
 import Element from 'zrender/src/Element';
 
-class Component {
+class ComponentView {
 
     // [Caution]: for compat the previous "class extend"
     // publich and protected fields must be initialized on
@@ -86,11 +86,11 @@ class Component {
     static registerClass: clazzUtil.ClassManager['registerClass'];
 };
 
-export type ComponentViewConstructor = typeof Component
+export type ComponentViewConstructor = typeof ComponentView
     & clazzUtil.ExtendableConstructor
     & clazzUtil.ClassManager;
 
-clazzUtil.enableClassExtend(Component as ComponentViewConstructor);
-clazzUtil.enableClassManagement(Component as ComponentViewConstructor, {registerWhenExtend: true});
+clazzUtil.enableClassExtend(ComponentView as ComponentViewConstructor);
+clazzUtil.enableClassManagement(ComponentView as ComponentViewConstructor, {registerWhenExtend: true});
 
-export default Component;
+export default ComponentView;


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