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 <[email protected]>
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: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to