You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@echarts.apache.org by su...@apache.org on 2020/03/01 00:31:55 UTC

[incubator-echarts] branch typescript updated (286efe8 -> a782931)

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

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


    from 286efe8  ts: add types for axisPointer
     new 5283e42  little typo. And move highDownXXX to ECElement.
     new a782931  Add geo and map series types. And enhance types a bit.

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 src/chart/map/MapSeries.ts              | 168 ++++++++++++--------
 src/chart/map/MapView.ts                |  78 ++++++---
 src/chart/map/backwardCompat.ts         |  11 +-
 src/chart/map/mapDataStatistic.ts       |  21 ++-
 src/chart/map/mapSymbolLayout.ts        |  14 +-
 src/chart/map/mapVisual.ts              |  11 +-
 src/chart/pie/PieSeries.ts              |  16 +-
 src/component/dataZoom/DataZoomModel.ts |   2 -
 src/component/geo.ts                    |  14 +-
 src/component/geo/GeoView.ts            |  30 ++--
 src/component/helper/MapDraw.ts         | 269 +++++++++++++++++---------------
 src/component/helper/selectableMixin.ts |   6 +-
 src/coord/View.ts                       | 197 +++++++++--------------
 src/coord/geo/Geo.ts                    | 162 ++++++++-----------
 src/coord/geo/GeoModel.ts               | 182 ++++++++++++++-------
 src/coord/geo/Region.ts                 | 111 ++++++-------
 src/coord/geo/fix/diaoyuIsland.ts       |   6 +-
 src/coord/geo/fix/geoCoord.ts           |   9 +-
 src/coord/geo/fix/nanhai.ts             |   4 +-
 src/coord/geo/fix/textCoord.ts          |   8 +-
 src/coord/geo/geoCreator.ts             |  70 +++++----
 src/coord/geo/geoJSONLoader.ts          |  23 +--
 src/coord/geo/geoSVGLoader.ts           |  33 ++--
 src/coord/geo/geoSourceManager.ts       |  83 +++++-----
 src/coord/geo/geoTypes.ts               | 116 ++++++++++++++
 src/coord/geo/mapDataStorage.ts         |  84 +++++-----
 src/coord/geo/parseGeoJson.ts           |  80 +++++-----
 src/coord/geo/prepareCustom.ts          |   9 +-
 src/coord/single/Single.ts              |   4 +-
 src/echarts.ts                          |  11 +-
 src/model/Component.ts                  |   1 -
 src/model/Series.ts                     |  12 +-
 src/util/graphic.ts                     |  41 ++---
 src/util/types.ts                       |  28 +++-
 src/view/Chart.ts                       |  18 +--
 35 files changed, 1090 insertions(+), 842 deletions(-)
 create mode 100644 src/coord/geo/geoTypes.ts


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


[incubator-echarts] 01/02: little typo. And move highDownXXX to ECElement.

Posted by su...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 5283e42cce673af9157abc3187c2ba54361746da
Author: 100pah <su...@gmail.com>
AuthorDate: Sun Mar 1 07:04:09 2020 +0800

    little typo. And move highDownXXX to ECElement.
---
 src/component/dataZoom/DataZoomModel.ts | 2 --
 src/coord/single/Single.ts              | 4 ++--
 src/util/graphic.ts                     | 4 ++--
 src/util/types.ts                       | 8 +++++---
 4 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/src/component/dataZoom/DataZoomModel.ts b/src/component/dataZoom/DataZoomModel.ts
index e508b21..d538d89 100644
--- a/src/component/dataZoom/DataZoomModel.ts
+++ b/src/component/dataZoom/DataZoomModel.ts
@@ -193,8 +193,6 @@ class DataZoomModel<Opts extends DataZoomOption = DataZoomOption> extends Compon
 
     init(option: Opts, parentModel: Model, ecModel: GlobalModel) {
 
-        this._rangePropMode = ['percent', 'percent'];
-
         var inputRawOption = retrieveRawOption(option);
 
         /**
diff --git a/src/coord/single/Single.ts b/src/coord/single/Single.ts
index b6a34cd..7bb223d 100644
--- a/src/coord/single/Single.ts
+++ b/src/coord/single/Single.ts
@@ -251,8 +251,8 @@ class Single implements CoordinateSystem, CoordinateSystemMaster {
 
 function getCoordSys(finder: ParsedModelFinder): Single {
     const seriesModel = finder.seriesModel;
-    const polarModel = finder.singleAxisModel as SingleAxisModel;
-    return polarModel && polarModel.coordinateSystem
+    const singleModel = finder.singleAxisModel as SingleAxisModel;
+    return singleModel && singleModel.coordinateSystem
         || seriesModel && seriesModel.coordinateSystem as Single;
 }
 
diff --git a/src/util/graphic.ts b/src/util/graphic.ts
index 9a6fba1..9fa2b48 100644
--- a/src/util/graphic.ts
+++ b/src/util/graphic.ts
@@ -681,8 +681,8 @@ export function setAsHighDownDispatcher(el: Element, asDispatcher: boolean) {
     const extendedEl = el as ExtendedDisplayable;
     // Make `highDownSilentOnTouch` and `highDownOnUpdate` only work after
     // `setAsHighDownDispatcher` called. Avoid it is modified by user unexpectedly.
-    extendedEl.__highDownSilentOnTouch = extendedEl.highDownSilentOnTouch;
-    extendedEl.__highDownOnUpdate = extendedEl.highDownOnUpdate;
+    extendedEl.__highDownSilentOnTouch = (el as ECElement).highDownSilentOnTouch;
+    extendedEl.__highDownOnUpdate = (el as ECElement).highDownOnUpdate;
 
     // Simple optimize, since this method might be
     // called for each elements of a group in some cases.
diff --git a/src/util/types.ts b/src/util/types.ts
index 2d954b7..468fe91 100644
--- a/src/util/types.ts
+++ b/src/util/types.ts
@@ -101,9 +101,11 @@ export interface ECElement extends Element {
     seriesIndex?: number;
     dataType?: string;
     tooltip?: CommonTooltipOption<unknown> & {
-        content?: string
-        formatterParams?: unknown
-    }
+        content?: string;
+        formatterParams?: unknown;
+    };
+    highDownSilentOnTouch?: boolean;
+    highDownOnUpdate?: (fromState: 'normal' | 'emphasis', toState: 'normal' | 'emphasis') => void;
 }
 
 export interface DataHost {


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


[incubator-echarts] 02/02: Add geo and map series types. And enhance types a bit.

Posted by su...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit a782931bab1c4b4bac2affbdbfbbd582c0451bf0
Author: 100pah <su...@gmail.com>
AuthorDate: Sun Mar 1 08:31:15 2020 +0800

    Add geo and map series types. And enhance types a bit.
---
 src/chart/map/MapSeries.ts              | 168 ++++++++++++--------
 src/chart/map/MapView.ts                |  78 ++++++---
 src/chart/map/backwardCompat.ts         |  11 +-
 src/chart/map/mapDataStatistic.ts       |  21 ++-
 src/chart/map/mapSymbolLayout.ts        |  14 +-
 src/chart/map/mapVisual.ts              |  11 +-
 src/chart/pie/PieSeries.ts              |  16 +-
 src/component/geo.ts                    |  14 +-
 src/component/geo/GeoView.ts            |  30 ++--
 src/component/helper/MapDraw.ts         | 269 +++++++++++++++++---------------
 src/component/helper/selectableMixin.ts |   6 +-
 src/coord/View.ts                       | 197 +++++++++--------------
 src/coord/geo/Geo.ts                    | 162 ++++++++-----------
 src/coord/geo/GeoModel.ts               | 182 ++++++++++++++-------
 src/coord/geo/Region.ts                 | 111 ++++++-------
 src/coord/geo/fix/diaoyuIsland.ts       |   6 +-
 src/coord/geo/fix/geoCoord.ts           |   9 +-
 src/coord/geo/fix/nanhai.ts             |   4 +-
 src/coord/geo/fix/textCoord.ts          |   8 +-
 src/coord/geo/geoCreator.ts             |  70 +++++----
 src/coord/geo/geoJSONLoader.ts          |  23 +--
 src/coord/geo/geoSVGLoader.ts           |  33 ++--
 src/coord/geo/geoSourceManager.ts       |  83 +++++-----
 src/coord/geo/geoTypes.ts               | 116 ++++++++++++++
 src/coord/geo/mapDataStorage.ts         |  84 +++++-----
 src/coord/geo/parseGeoJson.ts           |  80 +++++-----
 src/coord/geo/prepareCustom.ts          |   9 +-
 src/echarts.ts                          |  11 +-
 src/model/Component.ts                  |   1 -
 src/model/Series.ts                     |  12 +-
 src/util/graphic.ts                     |  37 +++--
 src/util/types.ts                       |  20 ++-
 src/view/Chart.ts                       |  18 +--
 33 files changed, 1081 insertions(+), 833 deletions(-)

diff --git a/src/chart/map/MapSeries.ts b/src/chart/map/MapSeries.ts
index a1f4b8c..6b1c8b1 100644
--- a/src/chart/map/MapSeries.ts
+++ b/src/chart/map/MapSeries.ts
@@ -17,38 +17,100 @@
 * under the License.
 */
 
-// @ts-nocheck
 
 import * as zrUtil from 'zrender/src/core/util';
 import createListSimply from '../helper/createListSimply';
 import SeriesModel from '../../model/Series';
 import {encodeHTML, addCommas} from '../../util/format';
-import {DataSelectableMixin} from '../../component/helper/selectableMixin';
+import {DataSelectableMixin, DataSelectableOptionMixin, SelectableTarget} from '../../component/helper/selectableMixin';
 import {retrieveRawAttr} from '../../data/helper/dataProvider';
 import geoSourceManager from '../../coord/geo/geoSourceManager';
 import {makeSeriesEncodeForNameBased} from '../../data/helper/sourceHelper';
+import { SeriesOption, BoxLayoutOptionMixin, SeriesEncodeOptionMixin, LabelOption, SeriesTooltipOption, OptionDataItemObject, OptionDataValueNumeric, ParsedValue, SeriesOnGeoOptionMixin } from '../../util/types';
+import { Dictionary } from 'zrender/src/core/types';
+import GeoModel, { GeoCommonOptionMixin, GeoItemStyleOption } from '../../coord/geo/GeoModel';
+import List from '../../data/List';
+import Model from '../../model/Model';
+import Geo from '../../coord/geo/Geo';
+
+interface MapDataItemOption extends
+    OptionDataItemObject<OptionDataValueNumeric>,
+    SelectableTarget {
+
+    itemStyle?: GeoItemStyleOption
+    label?: LabelOption
+
+    emphasis?: {
+        itemStyle?: GeoItemStyleOption
+        label?: LabelOption
+    }
+}
 
-var MapSeries = SeriesModel.extend({
+export type MapValueCalculationType = 'sum' | 'average' | 'min' | 'max';
 
-    type: 'series.map',
+export interface MapSeriesOption extends
+    SeriesOption,
+    GeoCommonOptionMixin,
+    // If `geoIndex` is not specified, a exclusive geo will be
+    // created. Otherwise use the specified geo component, and
+    // `map` and `mapType` are ignored.
+    SeriesOnGeoOptionMixin,
+    BoxLayoutOptionMixin,
+    DataSelectableOptionMixin,
+    SeriesEncodeOptionMixin {
 
-    dependencies: ['geo'],
+    coordinateSystem?: string;
+    silent?: boolean;
 
-    layoutMode: 'box',
+    // FIXME:TS formatter?
+    label?: LabelOption;
+    itemStyle?: GeoItemStyleOption;
 
-    /**
-     * Only first map series of same mapType will drawMap
-     * @type {boolean}
-     */
-    needsDrawMap: false,
+    tooltip?: SeriesTooltipOption;
 
-    /**
-     * Group of all map series with same mapType
-     * @type {boolean}
-     */
-    seriesGroup: [],
+    // FIXME:TS add marker types
+    markLine?: any;
+    markPoint?: any;
+    markArea?: any;
+
+    mapValueCalculation?: MapValueCalculationType;
+
+    showLegendSymbol?: boolean;
+
+    // @deprecated. Only for echarts2 backward compat.
+    geoCoord?: Dictionary<number[]>;
+
+    data?: OptionDataValueNumeric[] | OptionDataValueNumeric[][] | MapDataItemOption[]
+
+    emphasis?: {
+        // FIXME:TS formatter?
+        label?: LabelOption;
+        itemStyle?: GeoItemStyleOption;
+    };
+}
+
+class MapSeries extends SeriesModel<MapSeriesOption> {
+
+    static type = 'series.map' as const;
+    type = MapSeries.type;
+
+    static dependencies = ['geo'];
+
+    static layoutMode = 'box' as const;
+
+    coordinateSystem: Geo;
 
-    getInitialData: function (option) {
+    // -----------------
+    // Injected outside
+    originalData: List;
+    mainSeries: MapSeries;
+    // Only first map series of same mapType will drawMap.
+    needsDrawMap: boolean = false;
+    // Group of all map series with same mapType
+    seriesGroup: MapSeries[] = [];
+
+
+    getInitialData(option: MapSeriesOption): List {
         var data = createListSimply(this, {
             coordDimensions: ['value'],
             encodeDefaulter: zrUtil.curry(makeSeriesEncodeForNameBased, this)
@@ -56,7 +118,7 @@ var MapSeries = SeriesModel.extend({
         var valueDim = data.mapDimension('value');
         var dataNameMap = zrUtil.createHashMap();
         var selectTargetList = [];
-        var toAppendNames = [];
+        var toAppendNames = [] as string[];
 
         for (var i = 0, len = data.count(); i < len; i++) {
             var name = data.getName(i);
@@ -85,55 +147,51 @@ var MapSeries = SeriesModel.extend({
         data.appendValues([], toAppendNames);
 
         return data;
-    },
+    }
 
     /**
      * If no host geo model, return null, which means using a
      * inner exclusive geo model.
      */
-    getHostGeoModel: function () {
+    getHostGeoModel(): GeoModel {
         var geoIndex = this.option.geoIndex;
         return geoIndex != null
-            ? this.dependentModels.geo[geoIndex]
+            ? this.dependentModels.geo[geoIndex] as GeoModel
             : null;
-    },
+    }
 
-    getMapType: function () {
+    getMapType(): string {
         return (this.getHostGeoModel() || this).option.map;
-    },
+    }
 
-    // _fillOption: function (option, mapName) {
+    // _fillOption(option, mapName) {
         // Shallow clone
         // option = zrUtil.extend({}, option);
 
         // option.data = geoCreator.getFilledRegions(option.data, mapName, option.nameMap);
 
         // return option;
-    // },
+    // }
 
-    getRawValue: function (dataIndex) {
+    getRawValue(dataIndex: number): ParsedValue {
         // Use value stored in data instead because it is calculated from multiple series
         // FIXME Provide all value of multiple series ?
         var data = this.getData();
         return data.get(data.mapDimension('value'), dataIndex);
-    },
+    }
 
     /**
      * Get model of region
-     * @param  {string} name
-     * @return {module:echarts/model/Model}
      */
-    getRegionModel: function (regionName) {
+    getRegionModel(regionName: string): Model<MapDataItemOption> {
         var data = this.getData();
         return data.getItemModel(data.indexOfName(regionName));
-    },
+    }
 
     /**
      * Map tooltip formatter
-     *
-     * @param {number} dataIndex
      */
-    formatTooltip: function (dataIndex) {
+    formatTooltip(dataIndex: number): string {
         // FIXME orignalData and data is a bit confusing
         var data = this.getData();
         var formattedValue = addCommas(this.getRawValue(dataIndex));
@@ -144,7 +202,7 @@ var MapSeries = SeriesModel.extend({
         for (var i = 0; i < seriesGroup.length; i++) {
             var otherIndex = seriesGroup[i].originalData.indexOfName(name);
             var valueDim = data.mapDimension('value');
-            if (!isNaN(seriesGroup[i].originalData.get(valueDim, otherIndex))) {
+            if (!isNaN(seriesGroup[i].originalData.get(valueDim, otherIndex) as number)) {
                 seriesNames.push(
                     encodeHTML(seriesGroup[i].name)
                 );
@@ -153,12 +211,9 @@ var MapSeries = SeriesModel.extend({
 
         return seriesNames.join(', ') + '<br />'
             + encodeHTML(name + ' : ' + formattedValue);
-    },
+    }
 
-    /**
-     * @implement
-     */
-    getTooltipPosition: function (dataIndex) {
+    getTooltipPosition = function (this: MapSeries, dataIndex: number): number[] {
         if (dataIndex != null) {
             var name = this.getData().getName(dataIndex);
             var geo = this.coordinateSystem;
@@ -166,17 +221,17 @@ var MapSeries = SeriesModel.extend({
 
             return region && geo.dataToPoint(region.center);
         }
-    },
+    };
 
-    setZoom: function (zoom) {
+    setZoom(zoom: number): void {
         this.option.zoom = zoom;
-    },
+    }
 
-    setCenter: function (center) {
+    setCenter(center: number[]): void {
         this.option.center = center;
-    },
+    }
 
-    defaultOption: {
+    static defaultOption: MapSeriesOption = {
         // 一级层叠
         zlevel: 0,
         // 二级层叠
@@ -211,21 +266,7 @@ var MapSeries = SeriesModel.extend({
         // layoutCenter: [50%, 50%]
         // layoutSize: 100
 
-
-        // 数值合并方式,默认加和,可选为:
-        // 'sum' | 'average' | 'max' | 'min'
-        // mapValueCalculation: 'sum',
-        // 地图数值计算结果小数精度
-        // mapValuePrecision: 0,
-
-
-        // 显示图例颜色标识(系列标识的小圆点),图例开启时有效
         showLegendSymbol: true,
-        // 选择模式,默认关闭,可选single,multiple
-        // selectedMode: false,
-        dataRangeHoverLink: true,
-        // 是否开启缩放及漫游模式
-        // roam: false,
 
         // Define left-top, right-bottom coords to control view
         // For example, [ [180, 90], [-180, -90] ],
@@ -261,8 +302,9 @@ var MapSeries = SeriesModel.extend({
         }
     }
 
-});
+}
 
-zrUtil.mixin(MapSeries, DataSelectableMixin.prototype);
+interface MapSeries extends DataSelectableMixin<MapSeriesOption> {}
+zrUtil.mixin(MapSeries, DataSelectableMixin);
 
 export default MapSeries;
\ No newline at end of file
diff --git a/src/chart/map/MapView.ts b/src/chart/map/MapView.ts
index d95a6ed..e10ea18 100644
--- a/src/chart/map/MapView.ts
+++ b/src/chart/map/MapView.ts
@@ -17,21 +17,51 @@
 * 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 MapDraw from '../../component/helper/MapDraw';
+import ChartView from '../../view/Chart';
+import MapSeries from './MapSeries';
+import GlobalModel from '../../model/Global';
+import ExtensionAPI from '../../ExtensionAPI';
+import { Payload } from '../../util/types';
+import Model from '../../model/Model';
 
-var HIGH_DOWN_PROP = '__seriesMapHighDown';
-var RECORD_VERSION_PROP = '__seriesMapCallKey';
 
-export default echarts.extendChartView({
+var HIGH_DOWN_PROP = '__seriesMapHighDown' as const;
+var RECORD_VERSION_PROP = '__seriesMapCallKey' as const;
+var ORIGINAL_Z2 = '__mapOriginalZ2' as const;
 
-    type: 'map',
+interface CircleExtend extends graphic.Circle {
+    [ORIGINAL_Z2]: number;
+}
+interface HighDownRecord {
+    recordVersion: number;
+    circle: CircleExtend;
+    labelModel: Model;
+    hoverLabelModel: Model;
+    emphasisText: string;
+    normalText: string;
+};
+interface RegionGroupExtend extends graphic.Group {
+    [HIGH_DOWN_PROP]: HighDownRecord;
+    [RECORD_VERSION_PROP]: number;
+}
+
+class MapView extends ChartView {
+
+    static type = 'map' as const;
+    readonly type = MapView.type;
+
+    private _mapDraw: MapDraw;
 
-    render: function (mapModel, ecModel, api, payload) {
+    render(
+        mapModel: MapSeries,
+        ecModel: GlobalModel,
+        api: ExtensionAPI,
+        payload: Payload
+    ): void {
         // Not render if it is an toggleSelect action from self
         if (payload && payload.type === 'mapToggleSelect'
             && payload.from === this.uid
@@ -73,25 +103,25 @@ export default echarts.extendChartView({
 
         mapModel.get('showLegendSymbol') && ecModel.getComponent('legend')
             && this._renderSymbols(mapModel, ecModel, api);
-    },
+    }
 
-    remove: function () {
+    remove(): void {
         this._mapDraw && this._mapDraw.remove();
         this._mapDraw = null;
         this.group.removeAll();
-    },
+    }
 
-    dispose: function () {
+    dispose(): void {
         this._mapDraw && this._mapDraw.remove();
         this._mapDraw = null;
-    },
+    }
 
-    _renderSymbols: function (mapModel, ecModel, api) {
+    private _renderSymbols(mapModel: MapSeries, ecModel: GlobalModel, api: ExtensionAPI): void {
         var originalData = mapModel.originalData;
         var group = this.group;
 
         originalData.each(originalData.mapDimension('value'), function (value, originalDataIndex) {
-            if (isNaN(value)) {
+            if (isNaN(value as number)) {
                 return;
             }
 
@@ -144,7 +174,7 @@ export default echarts.extendChartView({
                 var labelModel = itemModel.getModel('label');
                 var hoverLabelModel = itemModel.getModel('emphasis.label');
 
-                var regionGroup = fullData.getItemGraphicEl(fullIndex);
+                var regionGroup = fullData.getItemGraphicEl(fullIndex) as RegionGroupExtend;
 
                 // `getFormattedLabel` needs to use `getData` inside. Here
                 // `mapModel.getData()` is shallow cloned from `mainSeries.getData()`.
@@ -167,7 +197,7 @@ export default echarts.extendChartView({
 
                 // Prevent from register listeners duplicatedly when roaming.
                 if (!highDownRecord) {
-                    highDownRecord = regionGroup[HIGH_DOWN_PROP] = {};
+                    highDownRecord = regionGroup[HIGH_DOWN_PROP] = {} as HighDownRecord;
                     var onEmphasis = zrUtil.curry(onRegionHighDown, true);
                     var onNormal = zrUtil.curry(onRegionHighDown, false);
                     regionGroup.on('mouseover', onEmphasis)
@@ -195,16 +225,16 @@ export default echarts.extendChartView({
             group.add(circle);
         });
     }
-});
+}
 
-function onRegionHighDown(toHighOrDown) {
+function onRegionHighDown(this: RegionGroupExtend, toHighOrDown: boolean): void {
     var highDownRecord = this[HIGH_DOWN_PROP];
     if (highDownRecord && highDownRecord.recordVersion === this[RECORD_VERSION_PROP]) {
         enterRegionHighDown(highDownRecord, toHighOrDown);
     }
 }
 
-function enterRegionHighDown(highDownRecord, toHighOrDown) {
+function enterRegionHighDown(highDownRecord: HighDownRecord, toHighOrDown: boolean): void {
     var circle = highDownRecord.circle;
     var labelModel = highDownRecord.labelModel;
     var hoverLabelModel = highDownRecord.hoverLabelModel;
@@ -218,7 +248,7 @@ function enterRegionHighDown(highDownRecord, toHighOrDown) {
             }, {isRectText: true, useInsideStyle: false}, true)
         );
         // Make label upper than others if overlaps.
-        circle.__mapOriginalZ2 = circle.z2;
+        circle[ORIGINAL_Z2] = circle.z2;
         circle.z2 += graphic.Z2_EMPHASIS_LIFT;
     }
     else {
@@ -229,9 +259,11 @@ function enterRegionHighDown(highDownRecord, toHighOrDown) {
         // Trigger normalize style like padding.
         circle.dirty(false);
 
-        if (circle.__mapOriginalZ2 != null) {
-            circle.z2 = circle.__mapOriginalZ2;
-            circle.__mapOriginalZ2 = null;
+        if (circle[ORIGINAL_Z2] != null) {
+            circle.z2 = circle[ORIGINAL_Z2];
+            circle[ORIGINAL_Z2] = null;
         }
     }
 }
+
+export default MapView;
diff --git a/src/chart/map/backwardCompat.ts b/src/chart/map/backwardCompat.ts
index d401323..1c450a0 100644
--- a/src/chart/map/backwardCompat.ts
+++ b/src/chart/map/backwardCompat.ts
@@ -17,19 +17,18 @@
 * under the License.
 */
 
-// @ts-nocheck
-
 import * as zrUtil from 'zrender/src/core/util';
+import { ECUnitOption, SeriesOption } from '../../util/types';
 
-export default function (option) {
+export default function (option: ECUnitOption) {
     // Save geoCoord
     var mapSeries = [];
-    zrUtil.each(option.series, function (seriesOpt) {
+    zrUtil.each(option.series, function (seriesOpt: SeriesOption) {
         if (seriesOpt && seriesOpt.type === 'map') {
             mapSeries.push(seriesOpt);
-            seriesOpt.map = seriesOpt.map || seriesOpt.mapType;
+            (seriesOpt as any).map = (seriesOpt as any).map || (seriesOpt as any).mapType;
             // Put x, y, width, height, x2, y2 in the top level
-            zrUtil.defaults(seriesOpt, seriesOpt.mapLocation);
+            zrUtil.defaults(seriesOpt, (seriesOpt as any).mapLocation);
         }
     });
 }
\ No newline at end of file
diff --git a/src/chart/map/mapDataStatistic.ts b/src/chart/map/mapDataStatistic.ts
index 4825c17..adb36b5 100644
--- a/src/chart/map/mapDataStatistic.ts
+++ b/src/chart/map/mapDataStatistic.ts
@@ -17,21 +17,18 @@
 * under the License.
 */
 
-// @ts-nocheck
 
 import * as zrUtil from 'zrender/src/core/util';
+import List from '../../data/List';
+import MapSeries, { MapValueCalculationType } from './MapSeries';
+import GlobalModel from '../../model/Global';
 
 // FIXME 公用?
-/**
- * @param {Array.<module:echarts/data/List>} datas
- * @param {string} statisticType 'average' 'sum'
- * @inner
- */
-function dataStatistics(datas, statisticType) {
-    var dataNameMap = {};
+function dataStatistics(datas: List[], statisticType: MapValueCalculationType): List {
+    var dataNameMap = {} as {[mapKey: string]: number[]};
 
     zrUtil.each(datas, function (data) {
-        data.each(data.mapDimension('value'), function (value, idx) {
+        data.each(data.mapDimension('value'), function (value: number, idx) {
             // Add prefix to avoid conflict with Object.prototype.
             var mapKey = 'ec-' + data.getName(idx);
             dataNameMap[mapKey] = dataNameMap[mapKey] || [];
@@ -69,9 +66,9 @@ function dataStatistics(datas, statisticType) {
     });
 }
 
-export default function (ecModel) {
-    var seriesGroups = {};
-    ecModel.eachSeriesByType('map', function (seriesModel) {
+export default function (ecModel: GlobalModel): void {
+    var seriesGroups = {} as {[key: string]: MapSeries[]};
+    ecModel.eachSeriesByType('map', function (seriesModel: MapSeries) {
         var hostGeoModel = seriesModel.getHostGeoModel();
         var key = hostGeoModel ? 'o' + hostGeoModel.id : 'i' + seriesModel.getMapType();
         (seriesGroups[key] = seriesGroups[key] || []).push(seriesModel);
diff --git a/src/chart/map/mapSymbolLayout.ts b/src/chart/map/mapSymbolLayout.ts
index 93d28b8..b3a4475 100644
--- a/src/chart/map/mapSymbolLayout.ts
+++ b/src/chart/map/mapSymbolLayout.ts
@@ -17,21 +17,23 @@
 * under the License.
 */
 
-// @ts-nocheck
 
 import * as zrUtil from 'zrender/src/core/util';
+import GlobalModel from '../../model/Global';
+import MapSeries from './MapSeries';
+import { Dictionary } from '../../util/types';
 
-export default function (ecModel) {
+export default function (ecModel: GlobalModel) {
 
-    var processedMapType = {};
+    var processedMapType = {} as {[mapType: string]: boolean};
 
-    ecModel.eachSeriesByType('map', function (mapSeries) {
+    ecModel.eachSeriesByType('map', function (mapSeries: MapSeries) {
         var mapType = mapSeries.getMapType();
         if (mapSeries.getHostGeoModel() || processedMapType[mapType]) {
             return;
         }
 
-        var mapSymbolOffsets = {};
+        var mapSymbolOffsets = {} as Dictionary<number>;
 
         zrUtil.each(mapSeries.seriesGroup, function (subMapSeries) {
             var geo = subMapSeries.coordinateSystem;
@@ -44,7 +46,7 @@ export default function (ecModel) {
                     // If input series.data is [11, 22, '-'/null/undefined, 44],
                     // it will be filled with NaN: [11, 22, NaN, 44] and NaN will
                     // not be drawn. So here must validate if value is NaN.
-                    if (!region || isNaN(value)) {
+                    if (!region || isNaN(value as number)) {
                         return;
                     }
 
diff --git a/src/chart/map/mapVisual.ts b/src/chart/map/mapVisual.ts
index f841bf8..617f729 100644
--- a/src/chart/map/mapVisual.ts
+++ b/src/chart/map/mapVisual.ts
@@ -1,3 +1,7 @@
+import GlobalModel from '../../model/Global';
+import MapSeries from './MapSeries';
+import { ZRColor } from '../../util/types';
+
 /*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
@@ -17,11 +21,10 @@
 * under the License.
 */
 
-// @ts-nocheck
 
-export default function (ecModel) {
-    ecModel.eachSeriesByType('map', function (seriesModel) {
-        var colorList = seriesModel.get('color');
+export default function (ecModel: GlobalModel) {
+    ecModel.eachSeriesByType('map', function (seriesModel: MapSeries) {
+        var colorList = seriesModel.get('color') as ZRColor[];
         var itemStyleModel = seriesModel.getModel('itemStyle');
 
         var areaColor = itemStyleModel.get('areaColor');
diff --git a/src/chart/pie/PieSeries.ts b/src/chart/pie/PieSeries.ts
index d3cb9d0..9a51351 100644
--- a/src/chart/pie/PieSeries.ts
+++ b/src/chart/pie/PieSeries.ts
@@ -34,7 +34,9 @@ import {
     ItemStyleOption,
     LabelOption,
     BoxLayoutOptionMixin,
-    OptionDataValueNumeric
+    OptionDataValueNumeric,
+    SeriesEncodeOptionMixin,
+    OptionDataItemObject
 } from '../../util/types';
 import List from '../../data/List';
 
@@ -46,10 +48,9 @@ interface PieLabelOption extends LabelOption {
     distanceToLabelLine?: number
 }
 
-interface PieDataItem {
-    name?: string
-
-    value?: OptionDataValueNumeric
+interface PieDataItem extends
+    OptionDataItemObject<OptionDataValueNumeric>,
+    SelectableTarget {
 
     itemStyle?: ItemStyleOption
     label?: PieLabelOption
@@ -65,7 +66,8 @@ export interface PieSeriesOption extends
     SeriesOption,
     DataSelectableOptionMixin,
     CircleLayoutOptionMixin,
-    BoxLayoutOptionMixin {
+    BoxLayoutOptionMixin,
+    SeriesEncodeOptionMixin {
 
     type: 'pie'
 
@@ -100,7 +102,7 @@ export interface PieSeriesOption extends
     animationType?: 'expansion' | 'scale'
     animationTypeUpdate?: 'transition' | 'expansion'
 
-    data?: OptionDataValueNumeric[] | PieDataItem[]
+    data?: OptionDataValueNumeric[] | OptionDataValueNumeric[][] | PieDataItem[]
 }
 
 class PieSeriesModel extends SeriesModel<PieSeriesOption> {
diff --git a/src/component/geo.ts b/src/component/geo.ts
index d949f7e..d6e4bc5 100644
--- a/src/component/geo.ts
+++ b/src/component/geo.ts
@@ -17,7 +17,6 @@
 * under the License.
 */
 
-// @ts-nocheck
 
 import * as echarts from '../echarts';
 import * as zrUtil from 'zrender/src/core/util';
@@ -26,15 +25,20 @@ import '../coord/geo/GeoModel';
 import '../coord/geo/geoCreator';
 import './geo/GeoView';
 import '../action/geoRoam';
+import { ActionInfo } from '../util/types';
+import GeoModel from '../coord/geo/GeoModel';
 
-function makeAction(method, actionInfo) {
+function makeAction(
+    method: 'toggleSelected' | 'select' | 'unSelect',
+    actionInfo: ActionInfo
+): void {
     actionInfo.update = 'updateView';
     echarts.registerAction(actionInfo, function (payload, ecModel) {
-        var selected = {};
+        var selected = {} as {[regionName: string]: boolean};
 
         ecModel.eachComponent(
             { mainType: 'geo', query: payload},
-            function (geoModel) {
+            function (geoModel: GeoModel) {
                 geoModel[method](payload.name);
                 var geo = geoModel.coordinateSystem;
                 zrUtil.each(geo.regions, function (region) {
@@ -61,4 +65,4 @@ makeAction('select', {
 makeAction('unSelect', {
     type: 'geoUnSelect',
     event: 'geounselected'
-});
\ No newline at end of file
+});
diff --git a/src/component/geo/GeoView.ts b/src/component/geo/GeoView.ts
index f132e20..e8b32b7 100644
--- a/src/component/geo/GeoView.ts
+++ b/src/component/geo/GeoView.ts
@@ -17,23 +17,31 @@
 * under the License.
 */
 
-// @ts-nocheck
 
 import MapDraw from '../helper/MapDraw';
-import * as echarts from '../../echarts';
+import ComponentView from '../../view/Component';
+import GlobalModel from '../../model/Global';
+import ExtensionAPI from '../../ExtensionAPI';
+import GeoModel from '../../coord/geo/GeoModel';
+import { Payload } from '../../util/types';
 
-export default echarts.extendComponentView({
+class GeoView extends ComponentView {
 
-    type: 'geo',
+    static type = 'geo' as const;
+    readonly type = GeoView.type;
 
-    init: function (ecModel, api) {
+    private _mapDraw: MapDraw;
+
+    init(ecModel: GlobalModel, api: ExtensionAPI) {
         var mapDraw = new MapDraw(api, true);
         this._mapDraw = mapDraw;
 
         this.group.add(mapDraw.group);
-    },
+    }
 
-    render: function (geoModel, ecModel, api, payload) {
+    render(
+        geoModel: GeoModel, ecModel: GlobalModel, api: ExtensionAPI, payload: Payload
+    ): void {
         // Not render if it is an toggleSelect action from self
         if (payload && payload.type === 'geoToggleSelect'
             && payload.from === this.uid
@@ -50,10 +58,12 @@ export default echarts.extendComponentView({
         }
 
         this.group.silent = geoModel.get('silent');
-    },
+    }
 
-    dispose: function () {
+    dispose(): void {
         this._mapDraw && this._mapDraw.remove();
     }
 
-});
\ No newline at end of file
+}
+
+export default GeoView;
diff --git a/src/component/helper/MapDraw.ts b/src/component/helper/MapDraw.ts
index a418341..46eebb1 100644
--- a/src/component/helper/MapDraw.ts
+++ b/src/component/helper/MapDraw.ts
@@ -17,8 +17,6 @@
 * under the License.
 */
 
-// @ts-nocheck
-
 import * as zrUtil from 'zrender/src/core/util';
 import RoamController from './RoamController';
 import * as roamHelper from '../../component/helper/roamHelper';
@@ -26,8 +24,25 @@ import {onIrrelevantElement} from '../../component/helper/cursorHelper';
 import * as graphic from '../../util/graphic';
 import geoSourceManager from '../../coord/geo/geoSourceManager';
 import {getUID} from '../../util/component';
+import ExtensionAPI from '../../ExtensionAPI';
+import GeoModel, { GeoCommonOptionMixin, GeoItemStyleOption } from '../../coord/geo/GeoModel';
+import MapSeries from '../../chart/map/MapSeries';
+import GlobalModel from '../../model/Global';
+import { Payload, ECElement } from '../../util/types';
+import GeoView from '../geo/GeoView';
+import MapView from '../../chart/map/MapView';
+import ComponentModel from '../../model/Component';
+import Region from '../../coord/geo/Region';
+import Element from 'zrender/src/Element';
+import Geo from '../../coord/geo/Geo';
+import Model from '../../model/Model';
+
+
+interface RegionsGroup extends graphic.Group {
+    __regions: Region[];
+}
 
-function getFixedItemStyle(model) {
+function getFixedItemStyle(model: Model<GeoItemStyleOption>) {
     var itemStyle = model.getItemStyle();
     var areaColor = model.get('areaColor');
 
@@ -40,137 +55,74 @@ function getFixedItemStyle(model) {
     return itemStyle;
 }
 
-function updateMapSelectHandler(mapDraw, mapOrGeoModel, regionsGroup, api, fromView) {
-    regionsGroup.off('click');
-    regionsGroup.off('mousedown');
-
-    if (mapOrGeoModel.get('selectedMode')) {
-
-        regionsGroup.on('mousedown', function () {
-            mapDraw._mouseDownFlag = true;
-        });
-
-        regionsGroup.on('click', function (e) {
-            if (!mapDraw._mouseDownFlag) {
-                return;
-            }
-            mapDraw._mouseDownFlag = false;
-
-            var el = e.target;
-            while (!el.__regions) {
-                el = el.parent;
-            }
-            if (!el) {
-                return;
-            }
-
-            var action = {
-                type: (mapOrGeoModel.mainType === 'geo' ? 'geo' : 'map') + 'ToggleSelect',
-                batch: zrUtil.map(el.__regions, function (region) {
-                    return {
-                        name: region.name,
-                        from: fromView.uid
-                    };
-                })
-            };
-            action[mapOrGeoModel.mainType + 'Id'] = mapOrGeoModel.id;
-
-            api.dispatchAction(action);
-
-            updateMapSelected(mapOrGeoModel, regionsGroup);
-        });
-    }
-}
-
-function updateMapSelected(mapOrGeoModel, regionsGroup) {
+function updateMapSelected(mapOrGeoModel: GeoModel | MapSeries, regionsGroup: RegionsGroup) {
     // FIXME
     regionsGroup.eachChild(function (otherRegionEl) {
-        zrUtil.each(otherRegionEl.__regions, function (region) {
+        zrUtil.each((otherRegionEl as RegionsGroup).__regions, function (region) {
             otherRegionEl.trigger(mapOrGeoModel.isSelected(region.name) ? 'emphasis' : 'normal');
         });
     });
 }
 
-/**
- * @alias module:echarts/component/helper/MapDraw
- * @param {module:echarts/ExtensionAPI} api
- * @param {boolean} updateGroup
- */
-function MapDraw(api, updateGroup) {
-
-    var group = new graphic.Group();
+class MapDraw {
 
-    /**
-     * @type {string}
-     * @private
-     */
-    this.uid = getUID('ec_map_draw');
+    private uid: string;
 
-    /**
-     * @type {module:echarts/component/helper/RoamController}
-     * @private
-     */
-    this._controller = new RoamController(api.getZr());
+    // @ts-ignore FIXME:TS
+    private _controller: RoamController;
 
-    /**
-     * @type {Object} {target, zoom, zoomLimit}
-     * @private
-     */
-    this._controllerHost = {target: updateGroup ? group : null};
+    private _controllerHost: {
+        target?: graphic.Group;
+        zoom?: number;
+        zoomLimit?: GeoCommonOptionMixin['scaleLimit'];
+    };
 
-    /**
-     * @type {module:zrender/container/Group}
-     * @readOnly
-     */
-    this.group = group;
+    readonly group: graphic.Group;
 
-    /**
-     * @type {boolean}
-     * @private
-     */
-    this._updateGroup = updateGroup;
+    private _updateGroup: boolean;
 
     /**
      * This flag is used to make sure that only one among
      * `pan`, `zoom`, `click` can occurs, otherwise 'selected'
      * action may be triggered when `pan`, which is unexpected.
-     * @type {booelan}
      */
-    this._mouseDownFlag;
+    private _mouseDownFlag: boolean;
 
-    /**
-     * @type {string}
-     */
-    this._mapName;
+    private _mapName: string;
 
-    /**
-     * @type {boolean}
-     */
-    this._initialized;
+    private _initialized: string;
 
-    /**
-     * @type {module:zrender/container/Group}
-     */
-    group.add(this._regionsGroup = new graphic.Group());
+    private _regionsGroup: RegionsGroup;
+
+    private _backgroundGroup: graphic.Group;
 
-    /**
-     * @type {module:zrender/container/Group}
-     */
-    group.add(this._backgroundGroup = new graphic.Group());
-}
 
-MapDraw.prototype = {
+    constructor(api: ExtensionAPI, updateGroup: boolean) {
+        var group = new graphic.Group();
+        this.uid = getUID('ec_map_draw');
+        // @ts-ignore FIXME:TS
+        this._controller = new RoamController(api.getZr());
+        this._controllerHost = {target: updateGroup ? group : null};
+        this.group = group;
+        this._updateGroup = updateGroup;
 
-    constructor: MapDraw,
+        group.add(this._regionsGroup = new graphic.Group() as RegionsGroup);
+        group.add(this._backgroundGroup = new graphic.Group());
+    }
 
-    draw: function (mapOrGeoModel, ecModel, api, fromView, payload) {
+    draw(
+        mapOrGeoModel: GeoModel | MapSeries,
+        ecModel: GlobalModel,
+        api: ExtensionAPI,
+        fromView: MapView | GeoView
+    ): void {
 
         var isGeo = mapOrGeoModel.mainType === 'geo';
 
         // Map series has data. GEO model that controlled by map series
         // will be assigned with map data. Other GEO model has no data.
-        var data = mapOrGeoModel.getData && mapOrGeoModel.getData();
-        isGeo && ecModel.eachComponent({mainType: 'series', subType: 'map'}, function (mapSeries) {
+        var data = (mapOrGeoModel as MapSeries).getData && (mapOrGeoModel as MapSeries).getData();
+        isGeo && ecModel.eachComponent({mainType: 'series', subType: 'map'}, function (mapSeries: MapSeries) {
             if (!data && mapSeries.getHostGeoModel() === mapOrGeoModel) {
                 data = mapSeries.getData();
             }
@@ -193,11 +145,11 @@ MapDraw.prototype = {
 
         regionsGroup.removeAll();
 
-        var itemStyleAccessPath = ['itemStyle'];
-        var hoverItemStyleAccessPath = ['emphasis', 'itemStyle'];
-        var labelAccessPath = ['label'];
-        var hoverLabelAccessPath = ['emphasis', 'label'];
-        var nameMap = zrUtil.createHashMap();
+        var itemStyleAccessPath = ['itemStyle'] as const;
+        var hoverItemStyleAccessPath = ['emphasis', 'itemStyle'] as const;
+        var labelAccessPath = ['label'] as const;
+        var hoverLabelAccessPath = ['emphasis', 'label'] as const;
+        var nameMap = zrUtil.createHashMap<RegionsGroup>();
 
         zrUtil.each(geo.regions, function (region) {
             // Consider in GeoJson properties.name may be duplicated, for example,
@@ -206,7 +158,7 @@ MapDraw.prototype = {
             // will make them share the same label and bring trouble in label
             // location calculation.
             var regionGroup = nameMap.get(region.name)
-                || nameMap.set(region.name, new graphic.Group());
+                || nameMap.set(region.name, new graphic.Group() as RegionsGroup);
 
             var compoundPath = new graphic.CompoundPath({
                 segmentIgnoreThreshold: 1,
@@ -216,14 +168,18 @@ MapDraw.prototype = {
             });
             regionGroup.add(compoundPath);
 
-            var regionModel = mapOrGeoModel.getRegionModel(region.name) || mapOrGeoModel;
+            const regionModel = mapOrGeoModel.getRegionModel(region.name) || mapOrGeoModel;
 
+            // @ts-ignore FIXME:TS fix the "compatible with each other"?
             var itemStyleModel = regionModel.getModel(itemStyleAccessPath);
+            // @ts-ignore FIXME:TS fix the "compatible with each other"?
             var hoverItemStyleModel = regionModel.getModel(hoverItemStyleAccessPath);
             var itemStyle = getFixedItemStyle(itemStyleModel);
             var hoverItemStyle = getFixedItemStyle(hoverItemStyleModel);
 
+            // @ts-ignore FIXME:TS fix the "compatible with each other"?
             var labelModel = regionModel.getModel(labelAccessPath);
+            // @ts-ignore FIXME:TS fix the "compatible with each other"?
             var hoverLabelModel = regionModel.getModel(hoverLabelAccessPath);
 
             var dataIdx;
@@ -240,7 +196,7 @@ MapDraw.prototype = {
                 }
             }
 
-            var transformPoint = function (point) {
+            var transformPoint = function (point: number[]): number[] {
                 return [
                     point[0] * scale[0] + position[0],
                     point[1] * scale[1] + position[1]
@@ -285,7 +241,7 @@ MapDraw.prototype = {
             var showLabel = labelModel.get('show');
             var hoverShowLabel = hoverLabelModel.get('show');
 
-            var isDataNaN = data && isNaN(data.get(data.mapDimension('value'), dataIdx));
+            var isDataNaN = data && isNaN(data.get(data.mapDimension('value'), dataIdx) as number);
             var itemLayout = data && data.getItemLayout(dataIdx);
             // In the following cases label will be drawn
             // 1. In map series and data value is NaN
@@ -314,7 +270,7 @@ MapDraw.prototype = {
                     silent: true
                 });
 
-                graphic.setLabelStyle(
+                graphic.setLabelStyle<typeof query>(
                     textEl.style, textEl.hoverStyle = {}, labelModel, hoverLabelModel,
                     {
                         labelFetcher: labelFetcher,
@@ -337,9 +293,9 @@ MapDraw.prototype = {
                 data.setItemGraphicEl(dataIdx, regionGroup);
             }
             else {
-                var regionModel = mapOrGeoModel.getRegionModel(region.name);
+                const regionModel = mapOrGeoModel.getRegionModel(region.name);
                 // Package custom mouse event for geo component
-                compoundPath.eventData = {
+                (compoundPath as Element as ECElement).eventData = {
                     componentType: 'geo',
                     componentIndex: mapOrGeoModel.componentIndex,
                     geoIndex: mapOrGeoModel.componentIndex,
@@ -351,6 +307,7 @@ MapDraw.prototype = {
             var groupRegions = regionGroup.__regions || (regionGroup.__regions = []);
             groupRegions.push(region);
 
+            // @ts-ignore FIXME:TS fix the "compatible with each other"?
             regionGroup.highDownSilentOnTouch = !!mapOrGeoModel.get('selectedMode');
             graphic.setHoverStyle(regionGroup, hoverItemStyle);
 
@@ -359,21 +316,21 @@ MapDraw.prototype = {
 
         this._updateController(mapOrGeoModel, ecModel, api);
 
-        updateMapSelectHandler(this, mapOrGeoModel, regionsGroup, api, fromView);
+        this._updateMapSelectHandler(mapOrGeoModel, regionsGroup, api, fromView);
 
         updateMapSelected(mapOrGeoModel, regionsGroup);
-    },
+    }
 
-    remove: function () {
+    remove(): void {
         this._regionsGroup.removeAll();
         this._backgroundGroup.removeAll();
         this._controller.dispose();
         this._mapName && geoSourceManager.removeGraphic(this._mapName, this.uid);
         this._mapName = null;
         this._controllerHost = {};
-    },
+    }
 
-    _updateBackground: function (geo) {
+    private _updateBackground(geo: Geo): void {
         var mapName = geo.map;
 
         if (this._mapName !== mapName) {
@@ -383,30 +340,35 @@ MapDraw.prototype = {
         }
 
         this._mapName = mapName;
-    },
+    }
 
-    _updateController: function (mapOrGeoModel, ecModel, api) {
+    private _updateController(
+        mapOrGeoModel: GeoModel | MapSeries, ecModel: GlobalModel, api: ExtensionAPI
+    ): void {
         var geo = mapOrGeoModel.coordinateSystem;
         var controller = this._controller;
         var controllerHost = this._controllerHost;
 
+        // @ts-ignore FIXME:TS
         controllerHost.zoomLimit = mapOrGeoModel.get('scaleLimit');
         controllerHost.zoom = geo.getZoom();
 
         // roamType is will be set default true if it is null
+        // @ts-ignore FIXME:TS
         controller.enable(mapOrGeoModel.get('roam') || false);
         var mainType = mapOrGeoModel.mainType;
 
-        function makeActionBase() {
+        function makeActionBase(): Payload {
             var action = {
                 type: 'geoRoam',
                 componentType: mainType
-            };
+            } as Payload;
             action[mainType + 'Id'] = mapOrGeoModel.id;
             return action;
         }
 
-        controller.off('pan').on('pan', function (e) {
+        // @ts-ignore FIXME:TS
+        controller.off('pan').on('pan', function (this: MapDraw, e) {
             this._mouseDownFlag = false;
 
             roamHelper.updateViewOnPan(controllerHost, e.dx, e.dy);
@@ -417,7 +379,8 @@ MapDraw.prototype = {
             }));
         }, this);
 
-        controller.off('zoom').on('zoom', function (e) {
+        // @ts-ignore FIXME:TS
+        controller.off('zoom').on('zoom', function (this: MapDraw, e) {
             this._mouseDownFlag = false;
 
             roamHelper.updateViewOnZoom(controllerHost, e.scale, e.originX, e.originY);
@@ -438,11 +401,63 @@ MapDraw.prototype = {
             }
         }, this);
 
+        // @ts-ignore FIXME:TS
         controller.setPointerChecker(function (e, x, y) {
             return geo.getViewRectAfterRoam().contain(x, y)
                 && !onIrrelevantElement(e, api, mapOrGeoModel);
         });
     }
+
+    private _updateMapSelectHandler(
+        mapOrGeoModel: GeoModel | MapSeries,
+        regionsGroup: RegionsGroup,
+        api: ExtensionAPI,
+        fromView: MapView | GeoView
+    ): void {
+        var mapDraw = this;
+
+        regionsGroup.off('click');
+        regionsGroup.off('mousedown');
+
+        // @ts-ignore FIXME:TS resolve type conflict
+        if (mapOrGeoModel.get('selectedMode')) {
+
+            regionsGroup.on('mousedown', function () {
+                mapDraw._mouseDownFlag = true;
+            });
+
+            regionsGroup.on('click', function (e) {
+                if (!mapDraw._mouseDownFlag) {
+                    return;
+                }
+                mapDraw._mouseDownFlag = false;
+
+                var el = e.target;
+                while (!(el as RegionsGroup).__regions) {
+                    el = el.parent;
+                }
+                if (!el) {
+                    return;
+                }
+
+                var action = {
+                    type: (mapOrGeoModel.mainType === 'geo' ? 'geo' : 'map') + 'ToggleSelect',
+                    batch: zrUtil.map((el as RegionsGroup).__regions, function (region) {
+                        return {
+                            name: region.name,
+                            from: fromView.uid
+                        };
+                    })
+                } as Payload;
+                action[mapOrGeoModel.mainType + 'Id'] = mapOrGeoModel.id;
+
+                api.dispatchAction(action);
+
+                updateMapSelected(mapOrGeoModel, regionsGroup);
+            });
+        }
+    }
+
 };
 
 export default MapDraw;
diff --git a/src/component/helper/selectableMixin.ts b/src/component/helper/selectableMixin.ts
index c45db1e..afc2415 100644
--- a/src/component/helper/selectableMixin.ts
+++ b/src/component/helper/selectableMixin.ts
@@ -28,9 +28,9 @@ import Model from '../../model/Model';
 import { Dictionary } from 'zrender/src/core/types';
 
 export interface SelectableTarget {
-    name: string,
-    value: any,
-    selected: boolean
+    name?: string;
+    selected?: boolean;
+    [key: string]: any;
 };
 
 export interface DataSelectableOptionMixin {
diff --git a/src/coord/View.ts b/src/coord/View.ts
index be65472..ebf0e42 100644
--- a/src/coord/View.ts
+++ b/src/coord/View.ts
@@ -17,8 +17,6 @@
 * under the License.
 */
 
-// @ts-nocheck
-
 /**
  * Simple view coordinate system
  * Mapping given x, y to transformd view x, y
@@ -29,89 +27,64 @@ import * as vector from 'zrender/src/core/vector';
 import * as matrix from 'zrender/src/core/matrix';
 import BoundingRect from 'zrender/src/core/BoundingRect';
 import Transformable from 'zrender/src/core/Transformable';
+import { CoordinateSystemMaster, CoordinateSystem } from './CoordinateSystem';
+import GlobalModel from '../model/Global';
+import { ParsedModelFinder } from '../util/model';
 
 var v2ApplyTransform = vector.applyTransform;
 
-// Dummy transform node
-function TransformDummy() {
-    Transformable.call(this);
-}
-zrUtil.mixin(TransformDummy, Transformable);
+class View extends Transformable implements CoordinateSystemMaster, CoordinateSystem {
 
-function View(name) {
-    /**
-     * @type {string}
-     */
-    this.name = name;
+    readonly type: string = 'view';
 
-    /**
-     * @type {Object}
-     */
-    this.zoomLimit;
+    static dimensions = ['x', 'y'];
+    readonly dimensions = ['x', 'y'];
 
-    Transformable.call(this);
+    readonly name: string;
 
-    this._roamTransformable = new TransformDummy();
+    zoomLimit: {
+        max?: number;
+        min?: number;
+    };
 
-    this._rawTransformable = new TransformDummy();
+    private _roamTransformable = new Transformable();
+    protected _rawTransformable = new Transformable();
 
-    this._center;
-    this._zoom;
-}
+    private _center: number[];
+    private _zoom: number;
+    protected _rect: BoundingRect;
+    private _viewRect: BoundingRect;
+    private _rawTransform: matrix.MatrixArray;
 
-View.prototype = {
 
-    constructor: View,
-
-    type: 'view',
-
-    /**
-     * @param {Array.<string>}
-     * @readOnly
-     */
-    dimensions: ['x', 'y'],
-
-    /**
-     * Set bounding rect
-     * @param {number} x
-     * @param {number} y
-     * @param {number} width
-     * @param {number} height
-     */
+    constructor(name: string) {
+        super();
+        this.name = name;
+    }
 
     // PENDING to getRect
-    setBoundingRect: function (x, y, width, height) {
+    setBoundingRect(x: number, y: number, width: number, height: number): BoundingRect {
         this._rect = new BoundingRect(x, y, width, height);
         return this._rect;
-    },
+    }
 
     /**
      * @return {module:zrender/core/BoundingRect}
      */
     // PENDING to getRect
-    getBoundingRect: function () {
+    getBoundingRect(): BoundingRect {
         return this._rect;
-    },
+    }
 
-    /**
-     * @param {number} x
-     * @param {number} y
-     * @param {number} width
-     * @param {number} height
-     */
-    setViewRect: function (x, y, width, height) {
+    setViewRect(x: number, y: number, width: number, height: number): void {
         this.transformTo(x, y, width, height);
         this._viewRect = new BoundingRect(x, y, width, height);
-    },
+    }
 
     /**
      * Transformed to particular position and size
-     * @param {number} x
-     * @param {number} y
-     * @param {number} width
-     * @param {number} height
      */
-    transformTo: function (x, y, width, height) {
+    transformTo(x: number, y: number, width: number, height: number): void {
         var rect = this.getBoundingRect();
         var rawTransform = this._rawTransformable;
 
@@ -122,25 +95,21 @@ View.prototype = {
         rawTransform.decomposeTransform();
 
         this._updateTransform();
-    },
+    }
 
     /**
      * Set center of view
-     * @param {Array.<number>} [centerCoord]
      */
-    setCenter: function (centerCoord) {
+    setCenter(centerCoord?: number[]): void {
         if (!centerCoord) {
             return;
         }
         this._center = centerCoord;
 
         this._updateCenterAndZoom();
-    },
+    }
 
-    /**
-     * @param {number} zoom
-     */
-    setZoom: function (zoom) {
+    setZoom(zoom: number): void {
         zoom = zoom || 1;
 
         var zoomLimit = this.zoomLimit;
@@ -155,39 +124,36 @@ View.prototype = {
         this._zoom = zoom;
 
         this._updateCenterAndZoom();
-    },
+    }
 
     /**
      * Get default center without roam
      */
-    getDefaultCenter: function () {
+    getDefaultCenter(): number[] {
         // Rect before any transform
         var rawRect = this.getBoundingRect();
         var cx = rawRect.x + rawRect.width / 2;
         var cy = rawRect.y + rawRect.height / 2;
 
         return [cx, cy];
-    },
+    }
 
-    getCenter: function () {
+    getCenter(): number[] {
         return this._center || this.getDefaultCenter();
-    },
+    }
 
-    getZoom: function () {
+    getZoom(): number {
         return this._zoom || 1;
-    },
+    }
 
-    /**
-     * @return {Array.<number}
-     */
-    getRoamTransform: function () {
+    getRoamTransform(): matrix.MatrixArray {
         return this._roamTransformable.getLocalTransform();
-    },
+    }
 
     /**
      * Remove roam
      */
-    _updateCenterAndZoom: function () {
+    private _updateCenterAndZoom(): void {
         // Must update after view transform updated
         var rawTransformMatrix = this._rawTransformable.getLocalTransform();
         var roamTransform = this._roamTransformable;
@@ -206,13 +172,12 @@ View.prototype = {
         roamTransform.scale = [zoom, zoom];
 
         this._updateTransform();
-    },
+    }
 
     /**
      * Update transform from roam and mapLocation
-     * @private
      */
-    _updateTransform: function () {
+    protected _updateTransform(): void {
         var roamTransformable = this._roamTransformable;
         var rawTransformable = this._rawTransformable;
 
@@ -228,9 +193,13 @@ View.prototype = {
         matrix.invert(this.invTransform, this.transform);
 
         this.decomposeTransform();
-    },
+    }
 
-    getTransformInfo: function () {
+    getTransformInfo(): {
+        roamTransform: matrix.MatrixArray,
+        rawScale: number[],
+        rawPosition: number[]
+    } {
         var roamTransform = this._roamTransformable.transform;
         var rawTransformable = this._rawTransformable;
         return {
@@ -238,89 +207,73 @@ View.prototype = {
             rawScale: zrUtil.slice(rawTransformable.scale),
             rawPosition: zrUtil.slice(rawTransformable.position)
         };
-    },
+    }
 
-    /**
-     * @return {module:zrender/core/BoundingRect}
-     */
-    getViewRect: function () {
+    getViewRect(): BoundingRect {
         return this._viewRect;
-    },
+    }
 
     /**
      * Get view rect after roam transform
-     * @return {module:zrender/core/BoundingRect}
      */
-    getViewRectAfterRoam: function () {
+    getViewRectAfterRoam(): BoundingRect {
         var rect = this.getBoundingRect().clone();
         rect.applyTransform(this.transform);
         return rect;
-    },
+    }
 
     /**
      * Convert a single (lon, lat) data item to (x, y) point.
-     * @param {Array.<number>} data
-     * @param {boolean} noRoam
-     * @param {Array.<number>} [out]
-     * @return {Array.<number>}
      */
-    dataToPoint: function (data, noRoam, out) {
+    dataToPoint(data: number[], noRoam?: boolean, out?: number[]): number[] {
         var transform = noRoam ? this._rawTransform : this.transform;
         out = out || [];
         return transform
             ? v2ApplyTransform(out, data, transform)
             : vector.copy(out, data);
-    },
+    }
 
     /**
      * Convert a (x, y) point to (lon, lat) data
-     * @param {Array.<number>} point
-     * @return {Array.<number>}
      */
-    pointToData: function (point) {
+    pointToData(point: number[]): number[] {
         var invTransform = this.invTransform;
         return invTransform
             ? v2ApplyTransform([], point, invTransform)
             : [point[0], point[1]];
-    },
+    }
 
-    /**
-     * @implements
-     * see {module:echarts/CoodinateSystem}
-     */
-    convertToPixel: zrUtil.curry(doConvert, 'dataToPoint'),
+    convertToPixel(ecModel: GlobalModel, finder: ParsedModelFinder, value: number[]): number[] {
+        var coordSys = getCoordSys(finder);
+        return coordSys === this ? coordSys.dataToPoint(value) : null;
+    }
 
-    /**
-     * @implements
-     * see {module:echarts/CoodinateSystem}
-     */
-    convertFromPixel: zrUtil.curry(doConvert, 'pointToData'),
+    convertFromPixel(ecModel: GlobalModel, finder: ParsedModelFinder, pixel: number[]): number[] {
+        var coordSys = getCoordSys(finder);
+        return coordSys === this ? coordSys.pointToData(pixel) : null;
+    }
 
     /**
      * @implements
-     * see {module:echarts/CoodinateSystem}
      */
-    containPoint: function (point) {
+    containPoint(point: number[]): boolean {
         return this.getViewRectAfterRoam().contain(point[0], point[1]);
     }
 
     /**
      * @return {number}
      */
-    // getScalarScale: function () {
+    // getScalarScale() {
     //     // Use determinant square root of transform to mutiply scalar
     //     var m = this.transform;
     //     var det = Math.sqrt(Math.abs(m[0] * m[3] - m[2] * m[1]));
     //     return det;
     // }
-};
-
-zrUtil.mixin(View, Transformable);
+}
 
-function doConvert(methodName, ecModel, finder, value) {
+function getCoordSys(finder: ParsedModelFinder): View {
     var seriesModel = finder.seriesModel;
-    var coordSys = seriesModel ? seriesModel.coordinateSystem : null; // e.g., graph.
-    return coordSys === this ? coordSys[methodName](value) : null;
+    return seriesModel ? seriesModel.coordinateSystem as View : null; // e.g., graph.
 }
 
-export default View;
\ No newline at end of file
+export default View;
diff --git a/src/coord/geo/Geo.ts b/src/coord/geo/Geo.ts
index 6cf370f..90f8076 100644
--- a/src/coord/geo/Geo.ts
+++ b/src/coord/geo/Geo.ts
@@ -17,71 +17,62 @@
 * under the License.
 */
 
-// @ts-nocheck
-
 import * as zrUtil from 'zrender/src/core/util';
 import BoundingRect from 'zrender/src/core/BoundingRect';
 import View from '../View';
 import geoSourceManager from './geoSourceManager';
+import Region from './Region';
+import { NameMap } from './geoTypes';
+import GlobalModel from '../../model/Global';
+import { ParsedModelFinder } from '../../util/model';
+import GeoModel from './GeoModel';
+import { resizeGeoType } from './geoCreator';
 
 
-/**
- * [Geo description]
- * For backward compatibility, the orginal interface:
- * `name, map, geoJson, specialAreas, nameMap` is kept.
- *
- * @param {string|Object} name
- * @param {string} map Map type
- *        Specify the positioned areas by left, top, width, height
- * @param {Object.<string, string>} [nameMap]
- *        Specify name alias
- * @param {boolean} [invertLongitute=true]
- */
-function Geo(name, map, nameMap, invertLongitute) {
+class Geo extends View {
 
-    View.call(this, name);
+    dimensions = ['lng', 'lat'];
 
-    /**
-     * Map type
-     * @type {string}
-     */
-    this.map = map;
+    type = 'geo';
 
-    var source = geoSourceManager.load(map, nameMap);
+    // map type
+    readonly map: string;
 
-    this._nameCoordMap = source.nameCoordMap;
-    this._regionsMap = source.regionsMap;
-    this._invertLongitute = invertLongitute == null ? true : invertLongitute;
+    private _nameCoordMap: zrUtil.HashMap<number[]>;
+    private _regionsMap: zrUtil.HashMap<Region>;
+    private _invertLongitute: boolean;
+    readonly regions: Region[];
 
-    /**
-     * @readOnly
-     */
-    this.regions = source.regions;
+    // Injected outside
+    aspectScale: number;
+    model: GeoModel;
+    resize: resizeGeoType;
 
     /**
-     * @type {module:zrender/src/core/BoundingRect}
+     * For backward compatibility, the orginal interface:
+     * `name, map, geoJson, specialAreas, nameMap` is kept.
+     *
+     * @param map Map type Specify the positioned areas by left, top, width, height.
+     * @param [nameMap] Specify name alias
      */
-    this._rect = source.boundingRect;
-}
+    constructor(name: string, map: string, nameMap?: NameMap, invertLongitute?: boolean) {
+        super(name);
 
-Geo.prototype = {
+        this.map = map;
 
-    constructor: Geo,
+        var source = geoSourceManager.load(map, nameMap);
 
-    type: 'geo',
+        this._nameCoordMap = source.nameCoordMap;
+        this._regionsMap = source.regionsMap;
+        this._invertLongitute = invertLongitute == null ? true : invertLongitute;
+        this.regions = source.regions;
+        this._rect = source.boundingRect;
+    }
 
     /**
-     * @param {Array.<string>}
-     * @readOnly
+     * Whether contain the given [lng, lat] coord.
      */
-    dimensions: ['lng', 'lat'],
-
-    /**
-     * If contain given lng,lat coord
-     * @param {Array.<number>}
-     * @readOnly
-     */
-    containCoord: function (coord) {
+    containCoord(coord: number[]) {
         var regions = this.regions;
         for (var i = 0; i < regions.length; i++) {
             if (regions[i].contain(coord)) {
@@ -89,12 +80,9 @@ Geo.prototype = {
             }
         }
         return false;
-    },
+    }
 
-    /**
-     * @override
-     */
-    transformTo: function (x, y, width, height) {
+    transformTo(x: number, y: number, width: number, height: number): void {
         var rect = this.getBoundingRect();
         var invertLongitute = this._invertLongitute;
 
@@ -121,57 +109,40 @@ Geo.prototype = {
         rawTransformable.updateTransform();
 
         this._updateTransform();
-    },
+    }
 
-    /**
-     * @param {string} name
-     * @return {module:echarts/coord/geo/Region}
-     */
-    getRegion: function (name) {
+    getRegion(name: string): Region {
         return this._regionsMap.get(name);
-    },
+    }
 
-    getRegionByCoord: function (coord) {
+    getRegionByCoord(coord: number[]): Region {
         var regions = this.regions;
         for (var i = 0; i < regions.length; i++) {
             if (regions[i].contain(coord)) {
                 return regions[i];
             }
         }
-    },
+    }
 
     /**
      * Add geoCoord for indexing by name
-     * @param {string} name
-     * @param {Array.<number>} geoCoord
      */
-    addGeoCoord: function (name, geoCoord) {
+    addGeoCoord(name: string, geoCoord: number[]): void {
         this._nameCoordMap.set(name, geoCoord);
-    },
+    }
 
     /**
      * Get geoCoord by name
-     * @param {string} name
-     * @return {Array.<number>}
      */
-    getGeoCoord: function (name) {
+    getGeoCoord(name: string): number[] {
         return this._nameCoordMap.get(name);
-    },
+    }
 
-    /**
-     * @override
-     */
-    getBoundingRect: function () {
+    getBoundingRect(): BoundingRect {
         return this._rect;
-    },
+    }
 
-    /**
-     * @param {string|Array.<number>} data
-     * @param {boolean} noRoam
-     * @param {Array.<number>} [out]
-     * @return {Array.<number>}
-     */
-    dataToPoint: function (data, noRoam, out) {
+    dataToPoint(data: number[], noRoam?: boolean, out?: number[]): number[] {
         if (typeof data === 'string') {
             // Map area name to geoCoord
             data = this.getGeoCoord(data);
@@ -179,36 +150,33 @@ Geo.prototype = {
         if (data) {
             return View.prototype.dataToPoint.call(this, data, noRoam, out);
         }
-    },
+    }
 
-    /**
-     * @override
-     */
-    convertToPixel: zrUtil.curry(doConvert, 'dataToPoint'),
+    convertToPixel(ecModel: GlobalModel, finder: ParsedModelFinder, value: number[]): number[] {
+        var coordSys = getCoordSys(finder);
+        return coordSys === this ? coordSys.dataToPoint(value) : null;
+    }
 
-    /**
-     * @override
-     */
-    convertFromPixel: zrUtil.curry(doConvert, 'pointToData')
+    convertFromPixel(ecModel: GlobalModel, finder: ParsedModelFinder, pixel: number[]): number[] {
+        var coordSys = getCoordSys(finder);
+        return coordSys === this ? coordSys.pointToData(pixel) : null;
+    }
 
 };
 
 zrUtil.mixin(Geo, View);
 
-function doConvert(methodName, ecModel, finder, value) {
-    var geoModel = finder.geoModel;
+function getCoordSys(finder: ParsedModelFinder): Geo {
+    var geoModel = finder.geoModel as GeoModel;
     var seriesModel = finder.seriesModel;
-
-    var coordSys = geoModel
+    return geoModel
         ? geoModel.coordinateSystem
         : seriesModel
         ? (
-            seriesModel.coordinateSystem // For map.
-            || (seriesModel.getReferringComponents('geo')[0] || {}).coordinateSystem
+            seriesModel.coordinateSystem as Geo // For map series.
+            || ((seriesModel.getReferringComponents('geo')[0] || {}) as GeoModel).coordinateSystem
         )
         : null;
-
-    return coordSys === this ? coordSys[methodName](value) : null;
 }
 
-export default Geo;
\ No newline at end of file
+export default Geo;
diff --git a/src/coord/geo/GeoModel.ts b/src/coord/geo/GeoModel.ts
index 4f9361c..da28ae0 100644
--- a/src/coord/geo/GeoModel.ts
+++ b/src/coord/geo/GeoModel.ts
@@ -17,50 +17,106 @@
 * under the License.
 */
 
-// @ts-nocheck
 
 import * as zrUtil from 'zrender/src/core/util';
 import * as modelUtil from '../../util/model';
 import ComponentModel from '../../model/Component';
 import Model from '../../model/Model';
-import {DataSelectableMixin} from '../../component/helper/selectableMixin';
+import {DataSelectableMixin, DataSelectableOptionMixin, SelectableTarget} from '../../component/helper/selectableMixin';
 import geoCreator from './geoCreator';
+import Geo from './Geo';
+import { ComponentOption, BoxLayoutOptionMixin, ItemStyleOption, ZRColor, LabelOption, DisplayState } from '../../util/types';
+import { RoamType } from '../../component/helper/RoamController';
+import { NameMap } from './geoTypes';
+import GlobalModel from '../../model/Global';
+
+
+export interface GeoItemStyleOption extends ItemStyleOption {
+    areaColor?: ZRColor;
+};
+interface GeoLabelOption extends LabelOption {
+    formatter?: string | ((params: GeoLabelFormatterDataParams) => string);
+}
+interface GeoLabelFormatterDataParams {
+    name: string;
+    status: DisplayState;
+}
+
+export interface RegoinOption extends SelectableTarget {
+    itemStyle?: GeoItemStyleOption;
+    label?: GeoLabelOption;
+    emphasis?: {
+        itemStyle?: GeoItemStyleOption;
+        label?: GeoLabelOption;
+    }
+};
 
-var GeoModel = ComponentModel.extend({
+export interface GeoCommonOptionMixin {
+    // Map name
+    map: string;
 
-    type: 'geo',
+    // Aspect is width / height. Inited to be geoJson bbox aspect
+    // This parameter is used for scale this aspect
+    aspectScale?: number;
 
-    /**
-     * @type {module:echarts/coord/geo/Geo}
-     */
-    coordinateSystem: null,
+    ///// Layout with center and size
+    // If you wan't to put map in a fixed size box with right aspect ratio
+    // This two properties may more conveninet
+    layoutCenter?: number[];
+    layoutSize?: number;
 
-    layoutMode: 'box',
+    // Define left-top, right-bottom coords to control view
+    // For example, [ [180, 90], [-180, -90] ]
+    // higher priority than center and zoom
+    boundingCoords?: number[][];
+    // Default on center of map
+    center?: number[];
+    roam?: RoamType;
+    zoom?: number;
 
-    init: function (option) {
-        ComponentModel.prototype.init.apply(this, arguments);
+    scaleLimit?: {
+        min?: number;
+        max?: number;
+    };
 
-        // Default label emphasis `show`
-        modelUtil.defaultEmphasis(option, 'label', ['show']);
-    },
+    nameMap?: NameMap;
+}
 
-    optionUpdated: function () {
-        var option = this.option;
-        var self = this;
+export interface GeoOption extends
+    ComponentOption,
+    BoxLayoutOptionMixin,
+    DataSelectableOptionMixin,
+    GeoCommonOptionMixin {
 
-        option.regions = geoCreator.getFilledRegions(option.regions, option.map, option.nameMap);
+    show?: boolean;
+    silent?: boolean;
 
-        this._optionModelMap = zrUtil.reduce(option.regions || [], function (optionModelMap, regionOpt) {
-            if (regionOpt.name) {
-                optionModelMap.set(regionOpt.name, new Model(regionOpt, self));
-            }
-            return optionModelMap;
-        }, zrUtil.createHashMap());
+    itemStyle?: GeoItemStyleOption;
+    label?: GeoLabelOption;
 
-        this.updateSelectedMap(option.regions);
-    },
+    emphasis?: {
+        itemStyle?: GeoItemStyleOption;
+        label?: GeoLabelOption;
+    };
+
+    regions: RegoinOption[];
+}
+
+var LABEL_FORMATTER_NORMAL = ['label', 'formatter'] as const;
+var LABEL_FORMATTER_EMPHASIS = ['emphasis', 'label', 'formatter'] as const;
+
+class GeoModel extends ComponentModel<GeoOption> {
 
-    defaultOption: {
+    static type = 'geo';
+    readonly type = GeoModel.type;
+
+    coordinateSystem: Geo;
+
+    static layoutMode = 'box' as const;
+
+    private _optionModelMap: zrUtil.HashMap<Model<RegoinOption>>;
+
+    static defaultOption: GeoOption = {
 
         zlevel: 0,
 
@@ -72,14 +128,6 @@ var GeoModel = ComponentModel.extend({
 
         top: 'center',
 
-
-        // width:,
-        // height:,
-        // right
-        // bottom
-
-        // Aspect is width / height. Inited to be geoJson bbox aspect
-        // This parameter is used for scale this aspect
         // If svg used, aspectScale is 1 by default.
         // aspectScale: 0.75,
         aspectScale: null,
@@ -131,33 +179,49 @@ var GeoModel = ComponentModel.extend({
         },
 
         regions: []
-    },
+    }
+
+    init(option: GeoOption, parentModel: Model, ecModel: GlobalModel): void {
+        super.init(option, parentModel, ecModel);
+        // Default label emphasis `show`
+        modelUtil.defaultEmphasis(option, 'label', ['show']);
+    }
+
+    optionUpdated(): void {
+        var option = this.option;
+        var self = this;
+
+        option.regions = geoCreator.getFilledRegions(option.regions, option.map, option.nameMap);
+
+        this._optionModelMap = zrUtil.reduce(option.regions || [], function (optionModelMap, regionOpt) {
+            if (regionOpt.name) {
+                optionModelMap.set(regionOpt.name, new Model(regionOpt, self));
+            }
+            return optionModelMap;
+        }, zrUtil.createHashMap());
+
+        this.updateSelectedMap(option.regions);
+    }
 
     /**
-     * Get model of region
-     * @param  {string} name
-     * @return {module:echarts/model/Model}
+     * Get model of region.
      */
-    getRegionModel: function (name) {
+    getRegionModel(name: string): Model<RegoinOption> {
         return this._optionModelMap.get(name) || new Model(null, this, this.ecModel);
-    },
+    }
 
     /**
      * Format label
-     * @param {string} name Region name
-     * @param {string} [status='normal'] 'normal' or 'emphasis'
-     * @return {string}
+     * @param name Region name
      */
-    getFormattedLabel: function (name, status) {
+    getFormattedLabel(name: string, status?: DisplayState) {
         var regionModel = this.getRegionModel(name);
-        var formatter = regionModel.get(
-            'label'
-            + (status === 'normal' ? '.' : status + '.')
-            + 'formatter'
-        );
+        var formatter = status === 'normal'
+            ? regionModel.get(LABEL_FORMATTER_NORMAL)
+            : regionModel.get(LABEL_FORMATTER_EMPHASIS);
         var params = {
             name: name
-        };
+        } as GeoLabelFormatterDataParams;
         if (typeof formatter === 'function') {
             params.status = status;
             return formatter(params);
@@ -165,17 +229,19 @@ var GeoModel = ComponentModel.extend({
         else if (typeof formatter === 'string') {
             return formatter.replace('{a}', name != null ? name : '');
         }
-    },
+    }
 
-    setZoom: function (zoom) {
+    setZoom(zoom: number): void {
         this.option.zoom = zoom;
-    },
+    }
 
-    setCenter: function (center) {
+    setCenter(center: number[]): void {
         this.option.center = center;
     }
-});
 
-zrUtil.mixin(GeoModel, DataSelectableMixin.prototype);
+}
+
+interface GeoModel extends DataSelectableMixin<GeoOption> {};
+zrUtil.mixin(GeoModel, DataSelectableMixin);
 
-export default GeoModel;
\ No newline at end of file
+export default GeoModel;
diff --git a/src/coord/geo/Region.ts b/src/coord/geo/Region.ts
index 8b545d3..962924f 100644
--- a/src/coord/geo/Region.ts
+++ b/src/coord/geo/Region.ts
@@ -17,62 +17,54 @@
 * under the License.
 */
 
-// @ts-nocheck
-
-/**
- * @module echarts/coord/geo/Region
- */
 
 import BoundingRect from 'zrender/src/core/BoundingRect';
 import * as bbox from 'zrender/src/core/bbox';
 import * as vec2 from 'zrender/src/core/vector';
 import * as polygonContain from 'zrender/src/contain/polygon';
+import { GeoJSON } from './geoTypes';
 
-/**
- * @param {string|Region} name
- * @param {Array} geometries
- * @param {Array.<number>} cp
- */
-function Region(name, geometries, cp) {
-
-    /**
-     * @type {string}
-     * @readOnly
-     */
-    this.name = name;
-
-    /**
-     * @type {Array.<Array>}
-     * @readOnly
-     */
-    this.geometries = geometries;
-
-    if (!cp) {
-        var rect = this.getBoundingRect();
-        cp = [
-            rect.x + rect.width / 2,
-            rect.y + rect.height / 2
-        ];
-    }
-    else {
-        cp = [cp[0], cp[1]];
-    }
-    /**
-     * @type {Array.<number>}
-     */
-    this.center = cp;
-}
 
-Region.prototype = {
+class Region {
+
+    readonly geometries: {
+        type: 'polygon'; // FIXME:TS Is there other types?
+        exterior: number[][];
+        interiors?: number[][][];
+    }[];
+
+    readonly name: string;
+
+    center: number[];
 
-    constructor: Region,
+    // Injected outside.
+    properties: GeoJSON['features'][0]['properties'];
 
-    properties: null,
+    private _rect: BoundingRect;
 
-    /**
-     * @return {module:zrender/core/BoundingRect}
-     */
-    getBoundingRect: function () {
+
+    constructor(
+        name: string,
+        geometries: Region['geometries'],
+        cp: GeoJSON['features'][0]['properties']['cp']
+    ) {
+        this.name = name;
+        this.geometries = geometries;
+
+        if (!cp) {
+            var rect = this.getBoundingRect();
+            cp = [
+                rect.x + rect.width / 2,
+                rect.y + rect.height / 2
+            ];
+        }
+        else {
+            cp = [cp[0], cp[1]];
+        }
+        this.center = cp;
+    }
+
+    getBoundingRect(): BoundingRect {
         var rect = this._rect;
         if (rect) {
             return rect;
@@ -81,8 +73,8 @@ Region.prototype = {
         var MAX_NUMBER = Number.MAX_VALUE;
         var min = [MAX_NUMBER, MAX_NUMBER];
         var max = [-MAX_NUMBER, -MAX_NUMBER];
-        var min2 = [];
-        var max2 = [];
+        var min2 = [] as number[];
+        var max2 = [] as number[];
         var geometries = this.geometries;
         for (var i = 0; i < geometries.length; i++) {
             // Only support polygon
@@ -103,13 +95,9 @@ Region.prototype = {
         return (this._rect = new BoundingRect(
             min[0], min[1], max[0] - min[0], max[1] - min[1]
         ));
-    },
+    }
 
-    /**
-     * @param {<Array.<number>} coord
-     * @return {boolean}
-     */
-    contain: function (coord) {
+    contain(coord: number[]): boolean {
         var rect = this.getBoundingRect();
         var geometries = this.geometries;
         if (!rect.contain(coord[0], coord[1])) {
@@ -125,7 +113,7 @@ Region.prototype = {
             if (polygonContain.contain(exterior, coord[0], coord[1])) {
                 // Not in the region if point is in the hole.
                 for (var k = 0; k < (interiors ? interiors.length : 0); k++) {
-                    if (polygonContain.contain(interiors[k])) {
+                    if (polygonContain.contain(interiors[k], coord[0], coord[1])) {
                         continue loopGeo;
                     }
                 }
@@ -133,9 +121,9 @@ Region.prototype = {
             }
         }
         return false;
-    },
+    }
 
-    transformTo: function (x, y, width, height) {
+    transformTo(x: number, y: number, width: number, height: number): void {
         var rect = this.getBoundingRect();
         var aspect = rect.width / rect.height;
         if (!width) {
@@ -170,15 +158,16 @@ Region.prototype = {
             rect.x + rect.width / 2,
             rect.y + rect.height / 2
         ];
-    },
+    }
 
-    cloneShallow: function (name) {
+    cloneShallow(name: string): Region {
         name == null && (name = this.name);
         var newRegion = new Region(name, this.geometries, this.center);
         newRegion._rect = this._rect;
         newRegion.transformTo = null; // Simply avoid to be called.
         return newRegion;
     }
-};
 
-export default Region;
\ No newline at end of file
+}
+
+export default Region;
diff --git a/src/coord/geo/fix/diaoyuIsland.ts b/src/coord/geo/fix/diaoyuIsland.ts
index 756a6fe..cc8b94b 100644
--- a/src/coord/geo/fix/diaoyuIsland.ts
+++ b/src/coord/geo/fix/diaoyuIsland.ts
@@ -1,3 +1,5 @@
+import Region from '../Region';
+
 /*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
@@ -17,8 +19,6 @@
 * under the License.
 */
 
-// @ts-nocheck
-
 // Fix for 钓鱼岛
 
 // var Region = require('../Region');
@@ -36,7 +36,7 @@ var points = [
     ]
 ];
 
-export default function (mapType, region) {
+export default function (mapType: string, region: Region) {
     if (mapType === 'china' && region.name === '台湾') {
         region.geometries.push({
             type: 'polygon',
diff --git a/src/coord/geo/fix/geoCoord.ts b/src/coord/geo/fix/geoCoord.ts
index f2ff5f8..6da9959 100644
--- a/src/coord/geo/fix/geoCoord.ts
+++ b/src/coord/geo/fix/geoCoord.ts
@@ -1,3 +1,6 @@
+import Region from '../Region';
+import { Dictionary } from 'zrender/src/core/types';
+
 /*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
@@ -17,15 +20,13 @@
 * under the License.
 */
 
-// @ts-nocheck
-
 var geoCoordMap = {
     'Russia': [100, 60],
     'United States': [-99, 38],
     'United States of America': [-99, 38]
-};
+} as Dictionary<number[]>;
 
-export default function (mapType, region) {
+export default function (mapType: string, region: Region) {
     if (mapType === 'world') {
         var geoCoord = geoCoordMap[region.name];
         if (geoCoord) {
diff --git a/src/coord/geo/fix/nanhai.ts b/src/coord/geo/fix/nanhai.ts
index 4bdfc74..44d6f9f 100644
--- a/src/coord/geo/fix/nanhai.ts
+++ b/src/coord/geo/fix/nanhai.ts
@@ -17,8 +17,6 @@
 * under the License.
 */
 
-// @ts-nocheck
-
 // Fix for 南海诸岛
 
 import * as zrUtil from 'zrender/src/core/util';
@@ -53,7 +51,7 @@ for (var i = 0; i < points.length; i++) {
     }
 }
 
-export default function (mapType, regions) {
+export default function (mapType: string, regions: Region[]) {
     if (mapType === 'china') {
         regions.push(new Region(
             '南海诸岛',
diff --git a/src/coord/geo/fix/textCoord.ts b/src/coord/geo/fix/textCoord.ts
index e1eaa9e..486fa0c 100644
--- a/src/coord/geo/fix/textCoord.ts
+++ b/src/coord/geo/fix/textCoord.ts
@@ -1,3 +1,6 @@
+import Region from '../Region';
+import { Dictionary } from 'zrender/src/core/types';
+
 /*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
@@ -17,7 +20,6 @@
 * under the License.
 */
 
-// @ts-nocheck
 
 var coordsOffsetMap = {
     '南海诸岛': [32, 80],
@@ -27,9 +29,9 @@ var coordsOffsetMap = {
     '澳门': [-10, 10],
     //'北京': [-10, 0],
     '天津': [5, 5]
-};
+} as Dictionary<number[]>;
 
-export default function (mapType, region) {
+export default function (mapType: string, region: Region) {
     if (mapType === 'china') {
         var coordFix = coordsOffsetMap[region.name];
         if (coordFix) {
diff --git a/src/coord/geo/geoCreator.ts b/src/coord/geo/geoCreator.ts
index aac7428..db19dc5 100644
--- a/src/coord/geo/geoCreator.ts
+++ b/src/coord/geo/geoCreator.ts
@@ -17,7 +17,6 @@
 * under the License.
 */
 
-// @ts-nocheck
 
 import {__DEV__} from '../../config';
 import * as echarts from '../../echarts';
@@ -27,13 +26,23 @@ import * as layout from '../../util/layout';
 import * as numberUtil from '../../util/number';
 import geoSourceManager from './geoSourceManager';
 import mapDataStorage from './mapDataStorage';
-
+import GeoModel, { GeoOption, RegoinOption } from './GeoModel';
+import MapSeries, { MapSeriesOption } from '../../chart/map/MapSeries';
+import ExtensionAPI from '../../ExtensionAPI';
+import { CoordinateSystemCreator } from '../CoordinateSystem';
+import { NameMap } from './geoTypes';
+import SeriesModel from '../../model/Series';
+import { SeriesOption, SeriesOnGeoOptionMixin } from '../../util/types';
+import { Dictionary } from 'zrender/src/core/types';
+import GlobalModel from '../../model/Global';
+import ComponentModel from '../../model/Component';
+
+
+export type resizeGeoType = typeof resizeGeo;
 /**
  * Resize method bound to the geo
- * @param {module:echarts/coord/geo/GeoModel|module:echarts/chart/map/MapModel} geoModel
- * @param {module:echarts/ExtensionAPI} api
  */
-function resizeGeo(geoModel, api) {
+function resizeGeo(this: Geo, geoModel: ComponentModel<GeoOption | MapSeriesOption>, api: ExtensionAPI): void {
 
     var boundingCoords = geoModel.get('boundingCoords');
     if (boundingCoords != null) {
@@ -51,8 +60,6 @@ function resizeGeo(geoModel, api) {
 
     var rect = this.getBoundingRect();
 
-    var boxLayoutOption;
-
     var center = geoModel.get('layoutCenter');
     var size = geoModel.get('layoutSize');
 
@@ -80,9 +87,9 @@ function resizeGeo(geoModel, api) {
         }
     }
 
-    var viewRect;
+    var viewRect: layout.LayoutRect;
     if (useCenterAndSize) {
-        var viewRect = {};
+        var viewRect = {} as layout.LayoutRect;
         if (aspect > 1) {
             // Width is same with size
             viewRect.width = size;
@@ -97,7 +104,7 @@ function resizeGeo(geoModel, api) {
     }
     else {
         // Use left/top/width/height
-        boxLayoutOption = geoModel.getBoxLayoutParams();
+        var boxLayoutOption = geoModel.getBoxLayoutParams() as Parameters<typeof layout.getLayoutRect>[0];
 
         // 0.75 rate
         boxLayoutOption.aspect = aspect;
@@ -114,27 +121,24 @@ function resizeGeo(geoModel, api) {
     this.setZoom(geoModel.get('zoom'));
 }
 
-/**
- * @param {module:echarts/coord/Geo} geo
- * @param {module:echarts/model/Model} model
- * @inner
- */
-function setGeoCoords(geo, model) {
+// Back compat for ECharts2, where the coord map is set on map series:
+// {type: 'map', geoCoord: {'cityA': [116.46,39.92], 'cityA': [119.12,24.61]}},
+function setGeoCoords(geo: Geo, model: MapSeries) {
     zrUtil.each(model.get('geoCoord'), function (geoCoord, name) {
         geo.addGeoCoord(name, geoCoord);
     });
 }
 
-var geoCreator = {
+class GeoCreator implements CoordinateSystemCreator {
 
     // For deciding which dimensions to use when creating list data
-    dimensions: Geo.prototype.dimensions,
+    dimensions = Geo.prototype.dimensions;
 
-    create: function (ecModel, api) {
-        var geoList = [];
+    create(ecModel: GlobalModel, api: ExtensionAPI): Geo[] {
+        var geoList = [] as Geo[];
 
         // FIXME Create each time may be slow
-        ecModel.eachComponent('geo', function (geoModel, idx) {
+        ecModel.eachComponent('geo', function (geoModel: GeoModel, idx) {
             var name = geoModel.get('map');
 
             var aspectScale = geoModel.get('aspectScale');
@@ -154,7 +158,7 @@ var geoCreator = {
             geo.zoomLimit = geoModel.get('scaleLimit');
             geoList.push(geo);
 
-            setGeoCoords(geo, geoModel);
+            // setGeoCoords(geo, geoModel);
 
             geoModel.coordinateSystem = geo;
             geo.model = geoModel;
@@ -168,15 +172,17 @@ var geoCreator = {
         ecModel.eachSeries(function (seriesModel) {
             var coordSys = seriesModel.get('coordinateSystem');
             if (coordSys === 'geo') {
-                var geoIndex = seriesModel.get('geoIndex') || 0;
+                var geoIndex = (
+                    seriesModel as SeriesModel<SeriesOption & SeriesOnGeoOptionMixin>
+                ).get('geoIndex') || 0;
                 seriesModel.coordinateSystem = geoList[geoIndex];
             }
         });
 
         // If has map series
-        var mapModelGroupBySeries = {};
+        var mapModelGroupBySeries = {} as Dictionary<MapSeries[]>;
 
-        ecModel.eachSeriesByType('map', function (seriesModel) {
+        ecModel.eachSeriesByType('map', function (seriesModel: MapSeries) {
             if (!seriesModel.getHostGeoModel()) {
                 var mapType = seriesModel.getMapType();
                 mapModelGroupBySeries[mapType] = mapModelGroupBySeries[mapType] || [];
@@ -209,16 +215,14 @@ var geoCreator = {
         });
 
         return geoList;
-    },
+    }
 
     /**
      * Fill given regions array
-     * @param  {Array.<Object>} originRegionArr
-     * @param  {string} mapName
-     * @param  {Object} [nameMap]
-     * @return {Array}
      */
-    getFilledRegions: function (originRegionArr, mapName, nameMap) {
+    getFilledRegions(
+        originRegionArr: RegoinOption[], mapName: string, nameMap?: NameMap
+    ): RegoinOption[] {
         // Not use the original
         var regionsArr = (originRegionArr || []).slice();
 
@@ -235,7 +239,9 @@ var geoCreator = {
 
         return regionsArr;
     }
-};
+}
+
+const geoCreator = new GeoCreator();
 
 echarts.registerCoordinateSystem('geo', geoCreator);
 
diff --git a/src/coord/geo/geoJSONLoader.ts b/src/coord/geo/geoJSONLoader.ts
index 3ec80f7..4e7df3e 100644
--- a/src/coord/geo/geoJSONLoader.ts
+++ b/src/coord/geo/geoJSONLoader.ts
@@ -17,8 +17,6 @@
 * under the License.
 */
 
-// @ts-nocheck
-
 import {each} from 'zrender/src/core/util';
 import parseGeoJson from './parseGeoJson';
 import {makeInner} from '../../util/model';
@@ -28,17 +26,22 @@ import fixNanhai from './fix/nanhai';
 import fixTextCoord from './fix/textCoord';
 import fixGeoCoord from './fix/geoCoord';
 import fixDiaoyuIsland from './fix/diaoyuIsland';
+import { GeoJSONMapRecord } from './mapDataStorage';
+import { BoundingRect } from 'zrender/src/export';
+import Region from './Region';
+
+type MapRecordInner = {
+    parsed: {
+        regions: Region[];
+        boundingRect: BoundingRect;
+    };
+};
 
-var inner = makeInner();
+var inner = makeInner<MapRecordInner>();
 
 export default {
 
-    /**
-     * @param {string} mapName
-     * @param {Object} mapRecord {specialAreas, geoJSON}
-     * @return {Object} {regions, boundingRect}
-     */
-    load: function (mapName, mapRecord) {
+    load(mapName: string, mapRecord: GeoJSONMapRecord): MapRecordInner['parsed'] {
 
         var parsed = inner(mapRecord).parsed;
 
@@ -84,7 +87,7 @@ export default {
     }
 };
 
-function getBoundingRect(regions) {
+function getBoundingRect(regions: Region[]): BoundingRect {
     var rect;
     for (var i = 0; i < regions.length; i++) {
         var regionRect = regions[i].getBoundingRect();
diff --git a/src/coord/geo/geoSVGLoader.ts b/src/coord/geo/geoSVGLoader.ts
index f735f8a..24b978c 100644
--- a/src/coord/geo/geoSVGLoader.ts
+++ b/src/coord/geo/geoSVGLoader.ts
@@ -17,25 +17,27 @@
 * under the License.
 */
 
-// @ts-nocheck
-
 import {parseSVG, makeViewBoxTransform} from 'zrender/src/tool/parseSVG';
 import Group from 'zrender/src/container/Group';
 import Rect from 'zrender/src/graphic/shape/Rect';
-import {assert, createHashMap} from 'zrender/src/core/util';
+import {assert, createHashMap, HashMap} from 'zrender/src/core/util';
 import BoundingRect from 'zrender/src/core/BoundingRect';
 import {makeInner} from '../../util/model';
+import { SVGMapRecord } from './mapDataStorage';
+
+type MapRecordInner = {
+    originRoot: Group;
+    boundingRect: BoundingRect;
+    // key: hostKey, value: root
+    rootMap: HashMap<Group>;
+    originRootHostKey: string;
+};
 
-var inner = makeInner();
+var inner = makeInner<MapRecordInner>();
 
 export default {
 
-    /**
-     * @param {string} mapName
-     * @param {Object} mapRecord {specialAreas, geoJSON}
-     * @return {Object} {root, boundingRect}
-     */
-    load: function (mapName, mapRecord) {
+    load(mapName: string, mapRecord: SVGMapRecord): ReturnType<typeof buildGraphic> {
         var originRoot = inner(mapRecord).originRoot;
         if (originRoot) {
             return {
@@ -52,7 +54,7 @@ export default {
         return graphic;
     },
 
-    makeGraphic: function (mapName, mapRecord, hostKey) {
+    makeGraphic(mapName: string, mapRecord: SVGMapRecord, hostKey: string): Group {
         // For performance consideration (in large SVG), graphic only maked
         // when necessary and reuse them according to hostKey.
         var field = inner(mapRecord);
@@ -79,7 +81,7 @@ export default {
         return rootMap.set(hostKey, root);
     },
 
-    removeGraphic: function (mapName, mapRecord, hostKey) {
+    removeGraphic(mapName: string, mapRecord: SVGMapRecord, hostKey: string): void {
         var field = inner(mapRecord);
         var rootMap = field.rootMap;
         rootMap && rootMap.removeKey(hostKey);
@@ -89,7 +91,12 @@ export default {
     }
 };
 
-function buildGraphic(mapRecord, boundingRect) {
+function buildGraphic(
+    mapRecord: SVGMapRecord, boundingRect?: BoundingRect
+): {
+    root: Group;
+    boundingRect: BoundingRect;
+} {
     var svgXML = mapRecord.svgXML;
     var result;
     var root;
diff --git a/src/coord/geo/geoSourceManager.ts b/src/coord/geo/geoSourceManager.ts
index 07554ac..2aa6696 100644
--- a/src/coord/geo/geoSourceManager.ts
+++ b/src/coord/geo/geoSourceManager.ts
@@ -17,32 +17,45 @@
 * under the License.
 */
 
-// @ts-nocheck
-
 import {__DEV__} from '../../config';
-import {each, createHashMap} from 'zrender/src/core/util';
-import mapDataStorage from './mapDataStorage';
+import {each, createHashMap, HashMap} from 'zrender/src/core/util';
+import mapDataStorage, { MapRecord } from './mapDataStorage';
 import geoJSONLoader from './geoJSONLoader';
 import geoSVGLoader from './geoSVGLoader';
 import BoundingRect from 'zrender/src/core/BoundingRect';
+import { NameMap } from './geoTypes';
+import Region from './Region';
+import { Dictionary } from 'zrender/src/core/types';
+import Group from 'zrender/src/container/Group';
+
 
+interface Loader {
+    load: (mapName: string, mapRecord: MapRecord) => {
+        regions?: Region[];
+        boundingRect?: BoundingRect;
+    };
+    makeGraphic?: (mapName: string, mapRecord: MapRecord, hostKey: string) => Group;
+    removeGraphic?: (mapName: string, mapRecord: MapRecord, hostKey: string) => void;
+}
 var loaders = {
     geoJSON: geoJSONLoader,
     svg: geoSVGLoader
-};
+} as Dictionary<Loader>;
 
 export default {
 
-    /**
-     * @param {string} mapName
-     * @param {Object} nameMap
-     * @return {Object} source {regions, regionsMap, nameCoordMap, boundingRect}
-     */
-    load: function (mapName, nameMap) {
-        var regions = [];
-        var regionsMap = createHashMap();
-        var nameCoordMap = createHashMap();
-        var boundingRect;
+    load: function (mapName: string, nameMap: NameMap): {
+        regions: Region[];
+        // Key: mapName
+        regionsMap: HashMap<Region>;
+        // Key: mapName
+        nameCoordMap: HashMap<number[]>;
+        boundingRect: BoundingRect
+    } {
+        var regions = [] as Region[];
+        var regionsMap = createHashMap<Region>();
+        var nameCoordMap = createHashMap<Region['center']>();
+        var boundingRect: BoundingRect;
         var mapRecords = retrieveMap(mapName);
 
         each(mapRecords, function (record) {
@@ -79,34 +92,32 @@ export default {
     },
 
     /**
-     * @param {string} mapName
-     * @param {string} hostKey For cache.
-     * @return {Array.<module:zrender/Element>} Roots.
+     * @param hostKey For cache.
+     * @return Roots.
      */
-    makeGraphic: makeInvoker('makeGraphic'),
+    makeGraphic: function (mapName: string, hostKey: string): Group[] {
+        var mapRecords = retrieveMap(mapName);
+        var results = [] as Group[];
+        each(mapRecords, function (record) {
+            var method = loaders[record.type].makeGraphic;
+            method && results.push(method(mapName, record, hostKey));
+        });
+        return results;
+    },
 
     /**
-     * @param {string} mapName
-     * @param {string} hostKey For cache.
+     * @param hostKey For cache.
      */
-    removeGraphic: makeInvoker('removeGraphic')
-};
-
-function makeInvoker(methodName) {
-    return function (mapName, hostKey) {
+    removeGraphic: function (mapName: string, hostKey: string): void {
         var mapRecords = retrieveMap(mapName);
-        var results = [];
-
         each(mapRecords, function (record) {
-            var method = loaders[record.type][methodName];
-            method && results.push(method(mapName, record, hostKey));
+            var method = loaders[record.type].makeGraphic;
+            method && method(mapName, record, hostKey);
         });
+    }
+};
 
-        return results;
-    };
-}
-
-function mapNotExistsError(mapName) {
+function mapNotExistsError(mapName: string): void {
     if (__DEV__) {
         console.error(
             'Map ' + mapName + ' not exists. The GeoJSON of the map must be provided.'
@@ -114,7 +125,7 @@ function mapNotExistsError(mapName) {
     }
 }
 
-function retrieveMap(mapName) {
+function retrieveMap(mapName: string): MapRecord[] {
     var mapRecords = mapDataStorage.retrieveMap(mapName) || [];
 
     if (__DEV__) {
diff --git a/src/coord/geo/geoTypes.ts b/src/coord/geo/geoTypes.ts
new file mode 100644
index 0000000..6096510
--- /dev/null
+++ b/src/coord/geo/geoTypes.ts
@@ -0,0 +1,116 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied.  See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+
+export interface NameMap {
+    [regionName: string]: string
+}
+
+export interface GeoSpecialAreas {
+    [areaName: string]: {
+        left: number;
+        top: number;
+        width?: number;
+        height?: number;
+    }
+}
+
+// Currently only `FeatureCollection` is supported in `parseGeoJson`?
+export interface GeoJSON extends GeoJSONFeatureCollection<GeoJSONGeometry> {
+}
+export interface GeoJSONCompressed extends GeoJSONFeatureCollection<GeoJSONGeometryCompressed> {
+    UTF8Encoding?: boolean;
+    UTF8Scale?: number;
+}
+interface GeoJSONFeatureCollection<G> {
+    type: 'FeatureCollection';
+    features: GeoJSONFeature<G>[];
+}
+interface GeoJSONFeature<G = GeoJSONGeometry> {
+    type: 'Feature';
+    id?: string | number;
+    properties: {
+        name?: string;
+        cp?: number[];
+        // id: string;
+        // childNum: number;
+        // Actual in GeoJSON spec, properties can be any.
+        [key: string]: any;
+    };
+    geometry: G;
+}
+type GeoJSONGeometry =
+    GeoJSONGeometryPoint
+    | GeoJSONGeometryMultiPoint
+    | GeoJSONGeometryLineString
+    | GeoJSONGeometryMultiLineString
+    | GeoJSONGeometryPolygon
+    | GeoJSONGeometryMultiPolygon
+    // Do not support `GeometryCollection` yet.
+    // | GeoJSONGeometryGeometryCollection
+
+type GeoJSONGeometryCompressed =
+    GeoJSONGeometryPoint
+    | GeoJSONGeometryMultiPoint
+    | GeoJSONGeometryLineString
+    | GeoJSONGeometryMultiLineString
+    // Currenly only Polygon and MultiPolygon can be parsed from compression.
+    | GeoJSONGeometryPolygonCompressed
+    | GeoJSONGeometryMultiPolygonCompressed
+    // Do not support `GeometryCollection` yet.
+    // | GeoJSONGeometryGeometryCollection
+
+interface GeoJSONGeometryPoint {
+    type: 'Point';
+    coordinates: number[];
+};
+interface GeoJSONGeometryMultiPoint {
+    type: 'MultiPoint';
+    coordinates: number[][];
+};
+interface GeoJSONGeometryLineString {
+    type: 'LineString';
+    coordinates: number[][];
+};
+interface GeoJSONGeometryMultiLineString {
+    type: 'MultiLineString';
+    coordinates: number[][][];
+};
+export interface GeoJSONGeometryPolygon {
+    type: 'Polygon';
+    coordinates: number[][][];
+};
+interface GeoJSONGeometryPolygonCompressed {
+    type: 'Polygon';
+    coordinates: string[];
+    encodeOffsets: number[][]
+};
+export interface GeoJSONGeometryMultiPolygon {
+    type: 'MultiPolygon';
+    coordinates: number[][][][];
+};
+interface GeoJSONGeometryMultiPolygonCompressed {
+    type: 'MultiPolygon';
+    coordinates: string[][];
+    encodeOffsets: number[][][];
+};
+// interface GeoJSONGeometryGeometryCollection {
+//      type: 'GeometryCollection';
+//      geometries: GeoJSONGeometry[];
+// };
diff --git a/src/coord/geo/mapDataStorage.ts b/src/coord/geo/mapDataStorage.ts
index 54be749..2453878 100644
--- a/src/coord/geo/mapDataStorage.ts
+++ b/src/coord/geo/mapDataStorage.ts
@@ -17,40 +17,40 @@
 * under the License.
 */
 
-// @ts-nocheck
-
 import {__DEV__} from '../../config';
 import {createHashMap, isString, isArray, each, assert} from 'zrender/src/core/util';
 import {parseXML} from 'zrender/src/tool/parseSVG';
+import { GeoSpecialAreas, GeoJSON, GeoJSONCompressed } from './geoTypes';
+import { Dictionary } from 'zrender/src/core/types';
 
 // For minimize the code size of common echarts package,
 // do not put too much logic in this module.
 
-export type GeoMapSVGSource = 'string' | Document;
-export type GeoMapGeoJSONSource = 'string' | object;
-export type GeoSpecialAreas = object;
-
-interface GeoMapGeoJSONDefinition {
-    geoJSON?: GeoMapGeoJSONSource;
-    geoJson?: GeoMapGeoJSONSource;
-    specialAreas?: GeoSpecialAreas;
-}
-interface GeoMapSVGDefinition {
-    svg?: GeoMapSVGSource;
+type SVGMapSource = 'string' | Document | SVGElement;
+type GeoJSONMapSource = 'string' | GeoJSON | GeoJSONCompressed;
+type MapInputObject = {
+    geoJSON?: GeoJSONMapSource;
+    geoJson?: GeoJSONMapSource;
+    svg?: SVGMapSource;
     specialAreas?: GeoSpecialAreas;
 }
-export type GeoMapDefinition = GeoMapGeoJSONDefinition | GeoMapSVGDefinition;
 
-interface GeoMapRecord {
-    type: 'geoJSON' | 'svg';
-    source: GeoMapGeoJSONSource | GeoMapSVGSource;
+export type MapRecord = GeoJSONMapRecord | SVGMapRecord;
+export interface GeoJSONMapRecord {
+    type: 'geoJSON';
+    source: GeoJSONMapSource;
+    specialAreas: GeoSpecialAreas;
+    geoJSON: GeoJSON | GeoJSONCompressed;
+}
+export interface SVGMapRecord {
+    type: 'svg';
+    source: SVGMapSource;
     specialAreas: GeoSpecialAreas;
-    geoJSON: object;
-    svgXML: Node
+    svgXML: ReturnType<typeof parseXML>;
 }
 
 
-var storage = createHashMap<GeoMapRecord[]>();
+var storage = createHashMap<MapRecord[]>();
 
 
 export default {
@@ -82,40 +82,40 @@ export default {
      */
     registerMap: function (
         mapName: string,
-        rawGeoJson: GeoMapDefinition | GeoMapDefinition[] | GeoMapGeoJSONSource,
+        rawDef: MapInputObject | MapRecord[] | GeoJSONMapSource,
         rawSpecialAreas?: GeoSpecialAreas
-    ): GeoMapRecord[] {
+    ): MapRecord[] {
 
-        var records;
+        var records: MapRecord[];
 
-        if (isArray(rawGeoJson)) {
-            records = rawGeoJson;
+        if (isArray(rawDef)) {
+            records = rawDef as MapRecord[];
         }
-        else if ((rawGeoJson as GeoMapSVGDefinition).svg) {
+        else if ((rawDef as MapInputObject).svg) {
             records = [{
                 type: 'svg',
-                source: (rawGeoJson as GeoMapSVGDefinition).svg,
-                specialAreas: (rawGeoJson as GeoMapSVGDefinition).specialAreas
-            }];
+                source: (rawDef as MapInputObject).svg,
+                specialAreas: (rawDef as MapInputObject).specialAreas
+            } as SVGMapRecord];
         }
         else {
             // Backward compatibility.
-            var geoSource = (rawGeoJson as GeoMapGeoJSONDefinition).geoJson
-                || (rawGeoJson as GeoMapGeoJSONDefinition).geoJSON;
-            if (geoSource && !(rawGeoJson as any).features) {
-                rawSpecialAreas = (rawGeoJson as GeoMapGeoJSONDefinition).specialAreas;
-                rawGeoJson = geoSource;
+            var geoSource = (rawDef as MapInputObject).geoJson
+                || (rawDef as MapInputObject).geoJSON;
+            if (geoSource && !(rawDef as GeoJSON).features) {
+                rawSpecialAreas = (rawDef as MapInputObject).specialAreas;
+                rawDef = geoSource;
             }
             records = [{
                 type: 'geoJSON',
-                source: rawGeoJson,
+                source: rawDef as GeoJSONMapSource,
                 specialAreas: rawSpecialAreas
-            }];
+            } as GeoJSONMapRecord];
         }
 
         each(records, function (record) {
             var type = record.type;
-            type === 'geoJson' && (type = record.type = 'geoJSON');
+            (type as any) === 'geoJson' && (type = record.type = 'geoJSON');
 
             var parse = parsers[type];
 
@@ -129,15 +129,15 @@ export default {
         return storage.set(mapName, records);
     },
 
-    retrieveMap: function (mapName: string): GeoMapRecord[] {
+    retrieveMap: function (mapName: string): MapRecord[] {
         return storage.get(mapName);
     }
 
 };
 
-var parsers = {
+var parsers: Dictionary<(record: MapRecord) => void> = {
 
-    geoJSON: function (record: GeoMapRecord): void {
+    geoJSON: function (record: GeoJSONMapRecord): void {
         var source = record.source;
         record.geoJSON = !isString(source)
             ? source
@@ -152,8 +152,8 @@ var parsers = {
     // if we do it here, the clone of zrender elements has to be
     // required. So we do it once for each geo instance, util real
     // performance issues call for optimizing it.
-    svg: function (record: GeoMapRecord): void {
-        record.svgXML = parseXML(record.source as GeoMapSVGSource);
+    svg: function (record: SVGMapRecord): void {
+        record.svgXML = parseXML(record.source as SVGMapSource);
     }
 
 };
diff --git a/src/coord/geo/parseGeoJson.ts b/src/coord/geo/parseGeoJson.ts
index 7bb5aef..463126c 100644
--- a/src/coord/geo/parseGeoJson.ts
+++ b/src/coord/geo/parseGeoJson.ts
@@ -17,61 +17,66 @@
 * under the License.
 */
 
-// @ts-nocheck
-
 /**
  * Parse and decode geo json
- * @module echarts/coord/geo/parseGeoJson
  */
 
 import * as zrUtil from 'zrender/src/core/util';
 import Region from './Region';
+import { GeoJSONCompressed, GeoJSON } from './geoTypes';
+
 
-function decode(json) {
-    if (!json.UTF8Encoding) {
-        return json;
+function decode(json: GeoJSONCompressed | GeoJSON): GeoJSON {
+    if (!(json as GeoJSONCompressed).UTF8Encoding) {
+        return json as GeoJSON;
     }
-    var encodeScale = json.UTF8Scale;
+    var jsonCompressed = json as GeoJSONCompressed;
+    var encodeScale = jsonCompressed.UTF8Scale;
     if (encodeScale == null) {
         encodeScale = 1024;
     }
 
-    var features = json.features;
+    var features = jsonCompressed.features;
 
     for (var f = 0; f < features.length; f++) {
         var feature = features[f];
         var geometry = feature.geometry;
-        var coordinates = geometry.coordinates;
-        var encodeOffsets = geometry.encodeOffsets;
-
-        for (var c = 0; c < coordinates.length; c++) {
-            var coordinate = coordinates[c];
 
-            if (geometry.type === 'Polygon') {
+        if (geometry.type === 'Polygon') {
+            let coordinates = geometry.coordinates;
+            for (let c = 0; c < coordinates.length; c++) {
                 coordinates[c] = decodePolygon(
-                    coordinate,
-                    encodeOffsets[c],
+                    coordinates[c],
+                    geometry.encodeOffsets[c],
                     encodeScale
-                );
+                ) as any;
             }
-            else if (geometry.type === 'MultiPolygon') {
+        }
+        else if (geometry.type === 'MultiPolygon') {
+            let coordinates = geometry.coordinates;
+            for (let c = 0; c < coordinates.length; c++) {
+                let coordinate = coordinates[c];
                 for (var c2 = 0; c2 < coordinate.length; c2++) {
-                    var polygon = coordinate[c2];
                     coordinate[c2] = decodePolygon(
-                        polygon,
-                        encodeOffsets[c][c2],
+                        coordinate[c2],
+                        geometry.encodeOffsets[c][c2],
                         encodeScale
-                    );
+                    ) as any;
                 }
             }
         }
     }
     // Has been decoded
-    json.UTF8Encoding = false;
-    return json;
+    jsonCompressed.UTF8Encoding = false;
+
+    return jsonCompressed as GeoJSON;
 }
 
-function decodePolygon(coordinate, encodeOffsets, encodeScale) {
+function decodePolygon(
+    coordinate: string,
+    encodeOffsets: number[],
+    encodeScale: number
+): number[][] {
     var result = [];
     var prevX = encodeOffsets[0];
     var prevY = encodeOffsets[1];
@@ -95,14 +100,9 @@ function decodePolygon(coordinate, encodeOffsets, encodeScale) {
     return result;
 }
 
-/**
- * @alias module:echarts/coord/geo/parseGeoJson
- * @param {Object} geoJson
- * @return {module:zrender/container/Group}
- */
-export default function (geoJson) {
+export default function (geoJson: GeoJSON | GeoJSONCompressed): Region[] {
 
-    decode(geoJson);
+    geoJson = decode(geoJson);
 
     return zrUtil.map(zrUtil.filter(geoJson.features, function (featureObj) {
         // Output of mapshaper may have geometry null
@@ -110,13 +110,12 @@ export default function (geoJson) {
             && featureObj.properties
             && featureObj.geometry.coordinates.length > 0;
     }), function (featureObj) {
-        var properties = featureObj.properties;
-        var geo = featureObj.geometry;
+        let properties = featureObj.properties;
+        let geo = featureObj.geometry;
 
-        var coordinates = geo.coordinates;
-
-        var geometries = [];
+        let geometries = [] as Region['geometries'];
         if (geo.type === 'Polygon') {
+            let coordinates = geo.coordinates;
             geometries.push({
                 type: 'polygon',
                 // According to the GeoJSON specification.
@@ -126,6 +125,7 @@ export default function (geoJson) {
             });
         }
         if (geo.type === 'MultiPolygon') {
+            let coordinates = geo.coordinates;
             zrUtil.each(coordinates, function (item) {
                 if (item[0]) {
                     geometries.push({
@@ -137,12 +137,12 @@ export default function (geoJson) {
             });
         }
 
-        var region = new Region(
+        let region = new Region(
             properties.name,
             geometries,
-            properties.cp
+            properties.cp,
         );
         region.properties = properties;
         return region;
     });
-}
\ No newline at end of file
+}
diff --git a/src/coord/geo/prepareCustom.ts b/src/coord/geo/prepareCustom.ts
index 8d329a8..df0fc16 100644
--- a/src/coord/geo/prepareCustom.ts
+++ b/src/coord/geo/prepareCustom.ts
@@ -17,11 +17,10 @@
 * under the License.
 */
 
-// @ts-nocheck
-
 import * as zrUtil from 'zrender/src/core/util';
+import Geo from './Geo';
 
-function dataToCoordSize(dataSize, dataItem) {
+function dataToCoordSize(this: Geo, dataSize: number[], dataItem: number[]): number[] {
     dataItem = dataItem || [0, 0];
     return zrUtil.map([0, 1], function (dimIdx) {
         var val = dataItem[dimIdx];
@@ -35,7 +34,7 @@ function dataToCoordSize(dataSize, dataItem) {
     }, this);
 }
 
-export default function (coordSys) {
+export default function (coordSys: Geo) {
     var rect = coordSys.getBoundingRect();
     return {
         coordSys: {
@@ -47,7 +46,7 @@ export default function (coordSys) {
             zoom: coordSys.getZoom()
         },
         api: {
-            coord: function (data) {
+            coord: function (data: number[]): number[] {
                 // do not provide "out" and noRoam param,
                 // Compatible with this usage:
                 // echarts.util.map(item.points, api.coord)
diff --git a/src/echarts.ts b/src/echarts.ts
index c369088..596573b 100644
--- a/src/echarts.ts
+++ b/src/echarts.ts
@@ -47,7 +47,7 @@ import Scheduler from './stream/Scheduler';
 import lightTheme from './theme/light';
 import darkTheme from './theme/dark';
 import './component/dataset';
-import mapDataStorage, { GeoMapDefinition, GeoMapGeoJSONSource, GeoSpecialAreas } from './coord/geo/mapDataStorage';
+import mapDataStorage from './coord/geo/mapDataStorage';
 import {CoordinateSystemMaster, CoordinateSystemCreator, CoordinateSystemHostModel} from './coord/CoordinateSystem';
 import { parseClassType } from './util/clazz';
 import {ECEventProcessor} from './util/ECEventProcessor';
@@ -2254,9 +2254,9 @@ export function setCanvasCreator(creator: () => HTMLCanvasElement): void {
  * Compatible with previous `echarts.registerMap`.
  */
 export function registerMap(
-    mapName: string,
-    geoJson: GeoMapDefinition | GeoMapDefinition[] | GeoMapGeoJSONSource,
-    specialAreas?: GeoSpecialAreas
+    mapName: Parameters<typeof mapDataStorage.registerMap>[0],
+    geoJson: Parameters<typeof mapDataStorage.registerMap>[1],
+    specialAreas?: Parameters<typeof mapDataStorage.registerMap>[2]
 ): void {
     mapDataStorage.registerMap(mapName, geoJson, specialAreas);
 }
@@ -2264,8 +2264,9 @@ export function registerMap(
 export function getMap(mapName: string) {
     // For backward compatibility, only return the first one.
     var records = mapDataStorage.retrieveMap(mapName);
-    // FIXME support SVG
+    // FIXME support SVG, where return not only records[0].
     return records && records[0] && {
+        // @ts-ignore
         geoJson: records[0].geoJSON,
         specialAreas: records[0].specialAreas
     };
diff --git a/src/model/Component.ts b/src/model/Component.ts
index 9c1ca02..c918474 100644
--- a/src/model/Component.ts
+++ b/src/model/Component.ts
@@ -271,7 +271,6 @@ class ComponentModel<Opt extends ComponentOption = ComponentOption> extends Mode
         });
     }
 
-
     getBoxLayoutParams() {
         // Consider itself having box layout configs.
         const boxLayoutModel = this as Model<ComponentOption & BoxLayoutOptionMixin>;
diff --git a/src/model/Series.ts b/src/model/Series.ts
index 4f91679..80c5a5f 100644
--- a/src/model/Series.ts
+++ b/src/model/Series.ts
@@ -327,10 +327,14 @@ class SeriesModel<Opt extends SeriesOption = SeriesOption> extends ComponentMode
         multipleSeries?: boolean,
         dataType?: string,
         renderMode?: TooltipRenderMode
-    ): {
-        html: string,
-        markers: {[markName: string]: string}
-    } {
+    ):
+        {
+            html: string,
+            markers: {[markName: string]: string}
+        }
+        // The override method can only return string
+        | string
+    {
 
         var series = this;
         renderMode = renderMode || 'html';
diff --git a/src/util/graphic.ts b/src/util/graphic.ts
index 9fa2b48..6f7ee97 100644
--- a/src/util/graphic.ts
+++ b/src/util/graphic.ts
@@ -678,7 +678,7 @@ export function setHoverStyle(el: Element, hoverStyle?: StyleProps) {
  */
 export function setAsHighDownDispatcher(el: Element, asDispatcher: boolean) {
     const disable = asDispatcher === false;
-    const extendedEl = el as ExtendedDisplayable;
+    const extendedEl = el as ExtendedElement;
     // Make `highDownSilentOnTouch` and `highDownOnUpdate` only work after
     // `setAsHighDownDispatcher` called. Avoid it is modified by user unexpectedly.
     extendedEl.__highDownSilentOnTouch = (el as ECElement).highDownSilentOnTouch;
@@ -720,29 +720,32 @@ export function getHighlightDigit(highlightKey: number) {
     return highlightDigit;
 }
 
+interface SetLabelStyleOpt<LDI> extends TextCommonParams {
+    defaultText?: string | (
+        (labelDataIndex: LDI, opt: SetLabelStyleOpt<LDI>) => string
+    ),
+    // Fetch text by `opt.labelFetcher.getFormattedLabel(opt.labelDataIndex, 'normal'/'emphasis', null, opt.labelDimIndex)`
+    labelFetcher?: {
+        getFormattedLabel?: (
+            // In MapDraw case it can be string (region name)
+            labelDataIndex: LDI,
+            state: DisplayState,
+            dataType: string,
+            labelDimIndex: number
+        ) => string
+    },
+    labelDataIndex?: LDI,
+    labelDimIndex?: number
+}
 /**
  * See more info in `setTextStyleCommon`.
  */
-export function setLabelStyle(
+export function setLabelStyle<LDI>(
     normalStyle: StyleProps,
     emphasisStyle: StyleProps,
     normalModel: Model,
     emphasisModel: Model,
-    opt?: {
-        defaultText?: string,
-        // Fetch text by `opt.labelFetcher.getFormattedLabel(opt.labelDataIndex, 'normal'/'emphasis', null, opt.labelDimIndex)`
-        labelFetcher?: {
-            getFormattedLabel?: (
-                labelDataIndex: number,
-                state:
-                DisplayState,
-                dataType: string,
-                labelDimIndex: number
-            ) => string
-        },
-        labelDataIndex?: number,
-        labelDimIndex?: number
-    } & TextCommonParams,
+    opt?: SetLabelStyleOpt<LDI>,
     normalSpecified?: StyleProps,
     emphasisSpecified?: StyleProps
 ) {
diff --git a/src/util/types.ts b/src/util/types.ts
index 468fe91..df725ed 100644
--- a/src/util/types.ts
+++ b/src/util/types.ts
@@ -405,7 +405,12 @@ export type OptionDataItem =
     | Dictionary<OptionDataValue>
     | ArrayLike<OptionDataValue>
     // FIXME: In some case (markpoint in geo (geo-map.html)), dataItem is {coord: [...]}
-    | {value: ArrayLike<OptionDataValue>}; // Only for `SOURCE_FORMAT_KEYED_ORIGINAL`
+    | OptionDataItemObject<OptionDataValue>;
+// Only for `SOURCE_FORMAT_KEYED_ORIGINAL`
+export type OptionDataItemObject<T> = {
+    name?: string
+    value?: T[] | T
+};
 export type OptionDataValue = string | number | Date;
 
 export type OptionDataValueNumeric = number | '-';
@@ -1026,4 +1031,15 @@ export interface SeriesOnPolarOptionMixin {
 export interface SeriesOnSingleOptionMixin {
     singleAxisIndex?: number
     singleAxisId?: string
-}
\ No newline at end of file
+}
+
+export interface SeriesOnGeoOptionMixin {
+    geoIndex?: number;
+}
+
+export interface SeriesEncodeOptionMixin {
+    datasetIndex?: number;
+    seriesLayoutBy?: SeriesLayoutBy;
+    dimentions?: DimensionName[];
+    encode?: OptionEncode
+}
diff --git a/src/view/Chart.ts b/src/view/Chart.ts
index d206483..19a1ec6 100644
--- a/src/view/Chart.ts
+++ b/src/view/Chart.ts
@@ -37,12 +37,12 @@ import { SeriesTaskContext, SeriesTask } from '../stream/Scheduler';
 import List from '../data/List';
 
 var inner = modelUtil.makeInner<{
-    updateMethod: keyof Chart
+    updateMethod: keyof ChartView
 }>();
 var renderPlanner = createRenderPlanner();
 
 
-class Chart {
+class ChartView {
 
     // [Caution]: for compat the previous "class extend"
     // publich and protected fields must be initialized on
@@ -67,7 +67,7 @@ class Chart {
     __id: string;
 
     static protoInitialize = (function () {
-        var proto = Chart.prototype;
+        var proto = ChartView.prototype;
         proto.type = 'chart';
     })();
 
@@ -178,7 +178,7 @@ class Chart {
         this.render(seriesModel, ecModel, api, payload);
     }
 
-    static markUpdateMethod(payload: Payload, methodName: keyof Chart): void {
+    static markUpdateMethod(payload: Payload, methodName: keyof ChartView): void {
         inner(payload).updateMethod = methodName;
     }
 
@@ -222,12 +222,12 @@ function toggleHighlight(data: List, payload: Payload, state: DisplayState) {
     }
 }
 
-export type ChartViewConstructor = typeof Chart
+export type ChartViewConstructor = typeof ChartView
     & clazzUtil.ExtendableConstructor
     & clazzUtil.ClassManager;
 
-clazzUtil.enableClassExtend(Chart as ChartViewConstructor, ['dispose']);
-clazzUtil.enableClassManagement(Chart as ChartViewConstructor, {registerWhenExtend: true});
+clazzUtil.enableClassExtend(ChartView as ChartViewConstructor, ['dispose']);
+clazzUtil.enableClassManagement(ChartView as ChartViewConstructor, {registerWhenExtend: true});
 
 
 function renderTaskPlan(context: SeriesTaskContext): StageHandlerPlanReturn {
@@ -244,7 +244,7 @@ function renderTaskReset(context: SeriesTaskContext): TaskResetCallbackReturn<Se
     var view = context.view;
 
     var updateMethod = payload && inner(payload).updateMethod;
-    var methodName: keyof Chart = progressiveRender
+    var methodName: keyof ChartView = progressiveRender
         ? 'incrementalPrepareRender'
         : (updateMethod && view[updateMethod])
         ? updateMethod
@@ -281,4 +281,4 @@ var progressMethodMap: {[method: string]: TaskResetCallbackReturn<SeriesTaskCont
     }
 };
 
-export default Chart;
+export default ChartView;


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