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

[incubator-echarts] branch typescript updated: ts: add types for calendar component

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

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


The following commit(s) were added to refs/heads/typescript by this push:
     new 53ca7a1  ts: add types for calendar component
53ca7a1 is described below

commit 53ca7a1362b12cb32f227467a174cd62223ce55e
Author: pissang <bm...@gmail.com>
AuthorDate: Sun Mar 15 21:46:48 2020 +0800

    ts: add types for calendar component
---
 src/chart/heatmap/HeatmapView.ts       |   5 +-
 src/chart/line/poly.ts                 |  19 +-
 src/component/calendar/CalendarView.ts | 139 +++++++-----
 src/coord/calendar/Calendar.ts         | 389 +++++++++++++++++++--------------
 src/coord/calendar/CalendarModel.ts    | 200 +++++++++++++----
 src/coord/calendar/prepareCustom.ts    |   7 +-
 src/echarts.ts                         |   4 +-
 src/util/types.ts                      |   2 +-
 8 files changed, 502 insertions(+), 263 deletions(-)

diff --git a/src/chart/heatmap/HeatmapView.ts b/src/chart/heatmap/HeatmapView.ts
index 587fd4e..2c8baba 100644
--- a/src/chart/heatmap/HeatmapView.ts
+++ b/src/chart/heatmap/HeatmapView.ts
@@ -30,7 +30,8 @@ import type PiecewiseModel from '../../component/visualMap/PiecewiseModel';
 import type ContinuousModel from '../../component/visualMap/ContinuousModel';
 import { CoordinateSystem, isCoordinateSystemType } from '../../coord/CoordinateSystem';
 import { StageHandlerProgressParams, Dictionary, OptionDataValue } from '../../util/types';
-import Cartesian2D from '../../coord/cartesian/Cartesian2D';
+import type Cartesian2D from '../../coord/cartesian/Cartesian2D';
+import type Calendar from '../../coord/calendar/Calendar';
 
 // Coord can be 'geo' 'bmap' 'amap' 'leaflet'...
 interface GeoLikeCoordSys extends CoordinateSystem {
@@ -158,7 +159,7 @@ class HeatmapView extends ChartView {
         incremental?: boolean
     ) {
 
-        var coordSys = seriesModel.coordinateSystem;
+        var coordSys = seriesModel.coordinateSystem as Cartesian2D | Calendar;
         var width;
         var height;
 
diff --git a/src/chart/line/poly.ts b/src/chart/line/poly.ts
index c9904f6..2ed8102 100644
--- a/src/chart/line/poly.ts
+++ b/src/chart/line/poly.ts
@@ -51,12 +51,19 @@ function drawSegment(
     smoothMonotone: 'x' | 'y' | 'none',
     connectNulls: boolean
 ) {
-    if (smoothMonotone === 'none' || !smoothMonotone) {
-        return drawNonMono.apply(null, arguments as any);
-    }
-    else {
-        return drawMono.apply(null, arguments as any);
-    }
+    return ((smoothMonotone === 'none' || !smoothMonotone) ? drawNonMono : drawMono)(
+        ctx,
+        points,
+        start,
+        segLen,
+        allLen,
+        dir,
+        smoothMin,
+        smoothMax,
+        smooth,
+        smoothMonotone,
+        connectNulls
+    );
 }
 
 /**
diff --git a/src/component/calendar/CalendarView.ts b/src/component/calendar/CalendarView.ts
index 699faea..b4e2475 100644
--- a/src/component/calendar/CalendarView.ts
+++ b/src/component/calendar/CalendarView.ts
@@ -17,13 +17,17 @@
 * 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 * as formatUtil from '../../util/format';
 import * as numberUtil from '../../util/number';
+import CalendarModel from '../../coord/calendar/CalendarModel';
+import {CalendarParsedDateRangeInfo, CalendarParsedDateInfo} from '../../coord/calendar/Calendar';
+import GlobalModel from '../../model/Global';
+import ExtensionAPI from '../../ExtensionAPI';
+import { LayoutOrient, OptionDataValueDate, ZRTextAlign, ZRTextVerticalAlign } from '../../util/types';
+import ComponentView from '../../view/Component';
+import { StyleProps } from 'zrender/src/graphic/Style';
 
 var MONTH_TEXT = {
     EN: [
@@ -45,35 +49,32 @@ var WEEK_TEXT = {
     CN: ['日', '一', '二', '三', '四', '五', '六']
 };
 
-export default echarts.extendComponentView({
+class CalendarView extends ComponentView {
 
-    type: 'calendar',
+    static type = 'calendar'
+    type = CalendarView.type
 
     /**
      * top/left line points
-     *  @private
      */
-    _tlpoints: null,
+    private _tlpoints: number[][]
 
     /**
      * bottom/right line points
-     *  @private
      */
-    _blpoints: null,
+    private _blpoints: number[][]
 
     /**
      * first day of month
-     *  @private
      */
-    _firstDayOfMonth: null,
+    private _firstDayOfMonth: CalendarParsedDateInfo[]
 
     /**
      * first day point of month
-     *  @private
      */
-    _firstDayPoints: null,
+    private _firstDayPoints: number[][]
 
-    render: function (calendarModel, ecModel, api) {
+    render(calendarModel: CalendarModel, ecModel: GlobalModel, api: ExtensionAPI) {
 
         var group = this.group;
 
@@ -95,10 +96,10 @@ export default echarts.extendComponentView({
         this._renderMonthText(calendarModel, orient, group);
 
         this._renderWeekText(calendarModel, rangeData, orient, group);
-    },
+    }
 
     // render day rect
-    _renderDayRect: function (calendarModel, rangeData, group) {
+    _renderDayRect(calendarModel: CalendarModel, rangeData: CalendarParsedDateRangeInfo, group: graphic.Group) {
         var coordSys = calendarModel.coordinateSystem;
         var itemRectStyleModel = calendarModel.getModel('itemStyle').getItemStyle();
         var sw = coordSys.getCellWidth();
@@ -126,17 +127,22 @@ export default echarts.extendComponentView({
             group.add(rect);
         }
 
-    },
+    }
 
     // render separate line
-    _renderLines: function (calendarModel, rangeData, orient, group) {
+    _renderLines(
+        calendarModel: CalendarModel,
+        rangeData: CalendarParsedDateRangeInfo,
+        orient: LayoutOrient,
+        group: graphic.Group
+    ) {
 
         var self = this;
 
         var coordSys = calendarModel.coordinateSystem;
 
-        var lineStyleModel = calendarModel.getModel('splitLine.lineStyle').getLineStyle();
-        var show = calendarModel.get('splitLine.show');
+        var lineStyleModel = calendarModel.getModel(['splitLine', 'lineStyle']).getLineStyle();
+        var show = calendarModel.get(['splitLine', 'show']);
 
         var lineWidth = lineStyleModel.lineWidth;
 
@@ -162,7 +168,7 @@ export default echarts.extendComponentView({
 
         addPoints(coordSys.getNextNDay(rangeData.end.time, 1).formatedDate);
 
-        function addPoints(date) {
+        function addPoints(date: OptionDataValueDate) {
 
             self._firstDayOfMonth.push(coordSys.getDateInfo(date));
             self._firstDayPoints.push(coordSys.dataToRect([date], false).tl);
@@ -182,10 +188,10 @@ export default echarts.extendComponentView({
         // render bottom/right line
         show && this._drawSplitline(self._getEdgesPoints(self._blpoints, lineWidth, orient), lineStyleModel, group);
 
-    },
+    }
 
     // get points at both ends
-    _getEdgesPoints: function (points, lineWidth, orient) {
+    _getEdgesPoints(points: number[][], lineWidth: number, orient: LayoutOrient) {
         var rs = [points[0].slice(), points[points.length - 1].slice()];
         var idx = orient === 'horizontal' ? 0 : 1;
 
@@ -194,33 +200,33 @@ export default echarts.extendComponentView({
         rs[1][idx] = rs[1][idx] + lineWidth / 2;
 
         return rs;
-    },
+    }
 
     // render split line
-    _drawSplitline: function (points, lineStyleModel, group) {
+    _drawSplitline(points: number[][], lineStyle: StyleProps, group: graphic.Group) {
 
         var poyline = new graphic.Polyline({
             z2: 20,
             shape: {
                 points: points
             },
-            style: lineStyleModel
+            style: lineStyle
         });
 
         group.add(poyline);
-    },
+    }
 
     // render month line of one week points
-    _getLinePointsOfOneWeek: function (calendarModel, date, orient) {
+    _getLinePointsOfOneWeek(calendarModel: CalendarModel, date: OptionDataValueDate, orient: LayoutOrient) {
 
         var coordSys = calendarModel.coordinateSystem;
-        date = coordSys.getDateInfo(date);
+        var parsedDate = coordSys.getDateInfo(date);
 
         var points = [];
 
         for (var i = 0; i < 7; i++) {
 
-            var tmpD = coordSys.getNextNDay(date.time, i);
+            var tmpD = coordSys.getNextNDay(parsedDate.time, i);
             var point = coordSys.dataToRect([tmpD.time], false);
 
             points[2 * tmpD.day] = point.tl;
@@ -229,9 +235,12 @@ export default echarts.extendComponentView({
 
         return points;
 
-    },
+    }
 
-    _formatterLabel: function (formatter, params) {
+    _formatterLabel<T extends { nameMap: string }>(
+        formatter: string | ((params: T) => string),
+        params: T
+    ) {
 
         if (typeof formatter === 'string' && formatter) {
             return formatUtil.formatTplSimple(formatter, params);
@@ -243,12 +252,18 @@ export default echarts.extendComponentView({
 
         return params.nameMap;
 
-    },
+    }
 
-    _yearTextPositionControl: function (textEl, point, orient, position, margin) {
+    _yearTextPositionControl(
+        textEl: graphic.Text,
+        point: number[],
+        orient: LayoutOrient,
+        position: 'left' | 'right' | 'top' | 'bottom',
+        margin: number
+    ) {
 
         point = point.slice();
-        var aligns = ['center', 'bottom'];
+        var aligns: [ZRTextAlign, ZRTextVerticalAlign] = ['center', 'bottom'];
 
         if (position === 'bottom') {
             point[1] += margin;
@@ -278,10 +293,15 @@ export default echarts.extendComponentView({
                 textVerticalAlign: aligns[1]
             }
         };
-    },
+    }
 
     // render year
-    _renderYearText: function (calendarModel, rangeData, orient, group) {
+    _renderYearText(
+        calendarModel: CalendarModel,
+        rangeData: CalendarParsedDateRangeInfo,
+        orient: LayoutOrient,
+        group: graphic.Group
+    ) {
         var yearLabel = calendarModel.getModel('yearLabel');
 
         if (!yearLabel.get('show')) {
@@ -329,11 +349,17 @@ export default echarts.extendComponentView({
         yearText.attr(this._yearTextPositionControl(yearText, posPoints[pos], orient, pos, margin));
 
         group.add(yearText);
-    },
+    }
 
-    _monthTextPositionControl: function (point, isCenter, orient, position, margin) {
-        var align = 'left';
-        var vAlign = 'top';
+    _monthTextPositionControl(
+        point: number[],
+        isCenter: boolean,
+        orient: LayoutOrient,
+        position: 'start' | 'end',
+        margin: number
+    ) {
+        var align: ZRTextAlign = 'left';
+        var vAlign: ZRTextVerticalAlign = 'top';
         var x = point[0];
         var y = point[1];
 
@@ -366,10 +392,10 @@ export default echarts.extendComponentView({
             textAlign: align,
             textVerticalAlign: vAlign
         };
-    },
+    }
 
     // render month and year text
-    _renderMonthText: function (calendarModel, orient, group) {
+    _renderMonthText(calendarModel: CalendarModel, orient: LayoutOrient, group: graphic.Group) {
         var monthLabel = calendarModel.getModel('monthLabel');
 
         if (!monthLabel.get('show')) {
@@ -384,7 +410,7 @@ export default echarts.extendComponentView({
         var termPoints = [this._tlpoints, this._blpoints];
 
         if (zrUtil.isString(nameMap)) {
-            nameMap = MONTH_TEXT[nameMap.toUpperCase()] || [];
+            nameMap = MONTH_TEXT[nameMap.toUpperCase() as 'CN' | 'EN'] || [];
         }
 
         var idx = pos === 'start' ? 0 : 1;
@@ -422,9 +448,15 @@ export default echarts.extendComponentView({
 
             group.add(monthText);
         }
-    },
+    }
 
-    _weekTextPositionControl: function (point, orient, position, margin, cellSize) {
+    _weekTextPositionControl(
+        point: number[],
+        orient: LayoutOrient,
+        position: 'start' | 'end',
+        margin: number,
+        cellSize: number[]
+    ) {
         var align = 'center';
         var vAlign = 'middle';
         var x = point[0];
@@ -446,10 +478,15 @@ export default echarts.extendComponentView({
             textAlign: align,
             textVerticalAlign: vAlign
         };
-    },
+    }
 
     // render weeks
-    _renderWeekText: function (calendarModel, rangeData, orient, group) {
+    _renderWeekText(
+        calendarModel: CalendarModel,
+        rangeData: CalendarParsedDateRangeInfo,
+        orient: LayoutOrient,
+        group: graphic.Group
+    ) {
         var dayLabel = calendarModel.getModel('dayLabel');
 
         if (!dayLabel.get('show')) {
@@ -463,7 +500,7 @@ export default echarts.extendComponentView({
         var firstDayOfWeek = coordSys.getFirstDayOfWeek();
 
         if (zrUtil.isString(nameMap)) {
-            nameMap = WEEK_TEXT[nameMap.toUpperCase()] || [];
+            nameMap = WEEK_TEXT[nameMap.toUpperCase() as 'CN' | 'EN'] || [];
         }
 
         var start = coordSys.getNextNDay(
@@ -495,4 +532,6 @@ export default echarts.extendComponentView({
             group.add(weekText);
         }
     }
-});
\ No newline at end of file
+}
+
+ComponentView.registerClass(CalendarView);
\ No newline at end of file
diff --git a/src/coord/calendar/Calendar.ts b/src/coord/calendar/Calendar.ts
index 9ae0c16..c030807 100644
--- a/src/coord/calendar/Calendar.ts
+++ b/src/coord/calendar/Calendar.ts
@@ -17,65 +17,138 @@
 * under the License.
 */
 
-// @ts-nocheck
-
 import * as zrUtil from 'zrender/src/core/util';
 import * as layout from '../../util/layout';
 import * as numberUtil from '../../util/number';
-import CoordinateSystem from '../../CoordinateSystem';
+import { BoundingRect } from 'zrender/src/export';
+import CalendarModel from './CalendarModel';
+import GlobalModel from '../../model/Global';
+import ExtensionAPI from '../../ExtensionAPI';
+import {
+    LayoutOrient,
+    ScaleDataValue,
+    OptionDataValueDate,
+    SeriesOption,
+    SeriesOnCalendarOptionMixin
+} from '../../util/types';
+import { ParsedModelFinder } from '../../util/model';
+import { CoordinateSystem, CoordinateSystemMaster } from '../CoordinateSystem';
+import { __DEV__ } from '../../config';
+import SeriesModel from '../../model/Series';
+import CoordinateSystemManager from '../../CoordinateSystem';
+import { RectLike } from 'zrender/src/core/BoundingRect';
 
 // (24*60*60*1000)
 var PROXIMATE_ONE_DAY = 86400000;
 
-/**
- * Calendar
- *
- * @constructor
- *
- * @param {Object} calendarModel calendarModel
- * @param {Object} ecModel       ecModel
- * @param {Object} api           api
- */
-function Calendar(calendarModel, ecModel, api) {
-    this._model = calendarModel;
+
+export interface CalendarParsedDateRangeInfo {
+    range: [string, string],
+    start: CalendarParsedDateInfo
+    end: CalendarParsedDateInfo
+    allDay: number
+    weeks: number
+    nthWeek: number
+    fweek: number
+    lweek: number
+}
+
+export interface CalendarParsedDateInfo {
+    /**
+     * local full year, eg., '1940'
+     */
+    y: string
+    /**
+     * local month, from '01' ot '12',
+     */
+    m: string
+    /**
+     * local date, from '01' to '31' (if exists),
+     */
+    d: string
+    /**
+     * It is not date.getDay(). It is the location of the cell in a week, from 0 to 6,
+     */
+    day: number
+    /**
+     * Timestamp
+     */
+    time: number
+    /**
+     * yyyy-MM-dd
+     */
+    formatedDate: string
+    /**
+     * The original date object
+     */
+    date: Date
 }
 
-Calendar.prototype = {
+export interface CalendarCellRect {
+    contentShape: RectLike
+    center: number[]
+    tl: number[]
+    tr: number[]
+    br: number[]
+    bl: number[]
+}
 
-    constructor: Calendar,
+class Calendar implements CoordinateSystem, CoordinateSystemMaster {
 
-    type: 'calendar',
+    static readonly dimensions = ['time', 'value'];
+    static getDimensionInfo() {
+        return [{
+            name: 'time', type: 'time'
+        }, 'value'];
+    }
 
-    dimensions: ['time', 'value'],
+    readonly type = 'calendar'
 
+    readonly dimensions = Calendar.dimensions
+
+    private _model: CalendarModel
+
+    private _rect: BoundingRect;
+
+    private _sw: number
+    private _sh: number
+    private _orient: LayoutOrient
+
+    private _firstDayOfWeek: number
+
+    private _rangeInfo: CalendarParsedDateRangeInfo
+
+    private _lineWidth: number
+
+    constructor(calendarModel: CalendarModel, ecModel: GlobalModel, api: ExtensionAPI) {
+        this._model = calendarModel;
+    }
     // Required in createListFromData
-    getDimensionsInfo: function () {
-        return [{name: 'time', type: 'time'}, 'value'];
-    },
+    getDimensionsInfo = Calendar.getDimensionInfo
 
-    getRangeInfo: function () {
+    getRangeInfo() {
         return this._rangeInfo;
-    },
+    }
 
-    getModel: function () {
+    getModel() {
         return this._model;
-    },
+    }
 
-    getRect: function () {
+    getRect() {
         return this._rect;
-    },
+    }
 
-    getCellWidth: function () {
+    getCellWidth() {
         return this._sw;
-    },
+    }
 
-    getCellHeight: function () {
+    getCellHeight() {
         return this._sh;
-    },
+    }
 
-    getOrient: function () {
+    getOrient() {
         return this._orient;
-    },
+    }
 
     /**
      * getFirstDayOfWeek
@@ -86,53 +159,42 @@ Calendar.prototype = {
      *
      * @return {number}
      */
-    getFirstDayOfWeek: function () {
+    getFirstDayOfWeek() {
         return this._firstDayOfWeek;
-    },
+    }
 
     /**
      * get date info
-     *
-     * @param  {string|number} date date
-     * @return {Object}
-     * {
-     *      y: string, local full year, eg., '1940',
-     *      m: string, local month, from '01' ot '12',
-     *      d: string, local date, from '01' to '31' (if exists),
-     *      day: It is not date.getDay(). It is the location of the cell in a week, from 0 to 6,
-     *      time: timestamp,
-     *      formatedDate: string, yyyy-MM-dd,
-     *      date: original date object.
      * }
      */
-    getDateInfo: function (date) {
+    getDateInfo(date: OptionDataValueDate): CalendarParsedDateInfo {
 
         date = numberUtil.parseDate(date);
 
         var y = date.getFullYear();
 
         var m = date.getMonth() + 1;
-        m = m < 10 ? '0' + m : m;
+        var mStr = m < 10 ? '0' + m : '' + m;
 
         var d = date.getDate();
-        d = d < 10 ? '0' + d : d;
+        var dStr = d < 10 ? '0' + d : '' + d;
 
         var day = date.getDay();
 
         day = Math.abs((day + 7 - this.getFirstDayOfWeek()) % 7);
 
         return {
-            y: y,
-            m: m,
-            d: d,
+            y: y + '',
+            m: mStr,
+            d: dStr,
             day: day,
             time: date.getTime(),
-            formatedDate: y + '-' + m + '-' + d,
+            formatedDate: y + '-' + mStr + '-' + dStr,
             date: date
         };
-    },
+    }
 
-    getNextNDay: function (date, n) {
+    getNextNDay(date: OptionDataValueDate, n: number) {
         n = n || 0;
         if (n === 0) {
             return this.getDateInfo(date);
@@ -142,9 +204,9 @@ Calendar.prototype = {
         date.setDate(date.getDate() + n);
 
         return this.getDateInfo(date);
-    },
+    }
 
-    update: function (ecModel, api) {
+    update(ecModel: GlobalModel, api: ExtensionAPI) {
 
         this._firstDayOfWeek = +this._model.getModel('dayLabel').get('firstDay');
         this._orient = this._model.get('orient');
@@ -153,12 +215,12 @@ Calendar.prototype = {
 
         this._rangeInfo = this._getRangeInfo(this._initRangeOption());
         var weeks = this._rangeInfo.weeks || 1;
-        var whNames = ['width', 'height'];
-        var cellSize = this._model.get('cellSize').slice();
+        var whNames = ['width', 'height'] as const;
+        var cellSize = this._model.getCellSize().slice();
         var layoutParams = this._model.getBoxLayoutParams();
         var cellNumbers = this._orient === 'horizontal' ? [weeks, 7] : [7, weeks];
 
-        zrUtil.each([0, 1], function (idx) {
+        zrUtil.each([0, 1] as const, function (idx) {
             if (cellSizeSpecified(cellSize, idx)) {
                 layoutParams[whNames[idx]] = cellSize[idx] * cellNumbers[idx];
             }
@@ -176,24 +238,20 @@ Calendar.prototype = {
             }
         });
 
-        function cellSizeSpecified(cellSize, idx) {
+        function cellSizeSpecified(cellSize: (number | 'auto')[], idx: number): cellSize is number[] {
             return cellSize[idx] != null && cellSize[idx] !== 'auto';
         }
 
-        this._sw = cellSize[0];
-        this._sh = cellSize[1];
-    },
+        // Has been calculated out number.
+        this._sw = cellSize[0] as number;
+        this._sh = cellSize[1] as number;
+    }
 
 
     /**
      * Convert a time data(time, value) item to (x, y) point.
-     *
-     * @override
-     * @param  {Array|number} data data
-     * @param  {boolean} [clamp=true] out of range
-     * @return {Array} point
      */
-    dataToPoint: function (data, clamp) {
+    dataToPoint(data: OptionDataValueDate | OptionDataValueDate[], clamp?: boolean) {
         zrUtil.isArray(data) && (data = data[0]);
         clamp == null && (clamp = true);
 
@@ -225,30 +283,22 @@ Calendar.prototype = {
             this._rect.y + week * this._sh + this._sh / 2
         ];
 
-    },
+    }
 
     /**
      * Convert a (x, y) point to time data
-     *
-     * @override
-     * @param  {string} point point
-     * @return {string}       data
      */
-    pointToData: function (point) {
+    pointToData(point: number[]): number {
 
         var date = this.pointToDate(point);
 
         return date && date.time;
-    },
+    }
 
     /**
      * Convert a time date item to (x, y) four point.
-     *
-     * @param  {Array} data  date[0] is date
-     * @param  {boolean} [clamp=true]  out of range
-     * @return {Object}       point
      */
-    dataToRect: function (data, clamp) {
+    dataToRect(data: OptionDataValueDate | OptionDataValueDate[], clamp?: boolean): CalendarCellRect {
         var point = this.dataToPoint(data, clamp);
 
         return {
@@ -282,7 +332,7 @@ Calendar.prototype = {
             ]
 
         };
-    },
+    }
 
     /**
      * Convert a (x, y) point to time date
@@ -290,7 +340,7 @@ Calendar.prototype = {
      * @param  {Array} point point
      * @return {Object}       date
      */
-    pointToDate: function (point) {
+    pointToDate(point: number[]): CalendarParsedDateInfo {
         var nthX = Math.floor((point[0] - this._rect.x) / this._sw) + 1;
         var nthY = Math.floor((point[1] - this._rect.y) / this._sh) + 1;
         var range = this._rangeInfo.range;
@@ -300,59 +350,77 @@ Calendar.prototype = {
         }
 
         return this._getDateByWeeksAndDay(nthX, nthY - 1, range);
-    },
+    }
 
-    /**
-     * @inheritDoc
-     */
-    convertToPixel: zrUtil.curry(doConvert, 'dataToPoint'),
+    convertToPixel(ecModel: GlobalModel, finder: ParsedModelFinder, value: ScaleDataValue | ScaleDataValue[]) {
+        const coordSys = getCoordSys(finder);
+        return coordSys === this ? coordSys.dataToPoint(value) : null;
+    }
 
-    /**
-     * @inheritDoc
-     */
-    convertFromPixel: zrUtil.curry(doConvert, 'pointToData'),
+    convertFromPixel(ecModel: GlobalModel, finder: ParsedModelFinder, pixel: number[]) {
+        const coordSys = getCoordSys(finder);
+        return coordSys === this ? coordSys.pointToData(pixel) : null;
+    }
+
+    containPoint(point: number[]): boolean {
+        console.warn('Not implemented.');
+        return false;
+    }
 
     /**
      * initRange
-     *
-     * @private
-     * @return {Array} [start, end]
+     * Normalize to an [start, end] array
      */
-    _initRangeOption: function () {
+    private _initRangeOption(): OptionDataValueDate[] {
         var range = this._model.get('range');
+        var normalizedRange: OptionDataValueDate[];
 
-        var rg = range;
-
-        if (zrUtil.isArray(rg) && rg.length === 1) {
-            rg = rg[0];
-        }
-
-        if (/^\d{4}$/.test(rg)) {
-            range = [rg + '-01-01', rg + '-12-31'];
+        // Convert [1990] to 1990
+        if (zrUtil.isArray(range) && range.length === 1) {
+            range = range[0];
         }
 
-        if (/^\d{4}[\/|-]\d{1,2}$/.test(rg)) {
+        if (!zrUtil.isArray(range)) {
+            let rangeStr = range.toString();
+            // One year.
+            if (/^\d{4}$/.test(rangeStr)) {
+                normalizedRange = [rangeStr + '-01-01', rangeStr + '-12-31'];
+            }
+            // One month
+            if (/^\d{4}[\/|-]\d{1,2}$/.test(rangeStr)) {
 
-            var start = this.getDateInfo(rg);
-            var firstDay = start.date;
-            firstDay.setMonth(firstDay.getMonth() + 1);
+                var start = this.getDateInfo(rangeStr);
+                var firstDay = start.date;
+                firstDay.setMonth(firstDay.getMonth() + 1);
 
-            var end = this.getNextNDay(firstDay, -1);
-            range = [start.formatedDate, end.formatedDate];
+                var end = this.getNextNDay(firstDay, -1);
+                normalizedRange = [start.formatedDate, end.formatedDate];
+            }
+            // One day
+            if (/^\d{4}[\/|-]\d{1,2}[\/|-]\d{1,2}$/.test(rangeStr)) {
+                normalizedRange = [rangeStr, rangeStr];
+            }
+        }
+        else {
+            normalizedRange = range;
         }
 
-        if (/^\d{4}[\/|-]\d{1,2}[\/|-]\d{1,2}$/.test(rg)) {
-            range = [rg, rg];
+        if (!normalizedRange) {
+            if (__DEV__) {
+                zrUtil.logError('Invalid date range.');
+            }
+            // Not handling it.
+            return range as OptionDataValueDate[];
         }
 
-        var tmp = this._getRangeInfo(range);
+        var tmp = this._getRangeInfo(normalizedRange);
 
         if (tmp.start.time > tmp.end.time) {
-            range.reverse();
+            normalizedRange.reverse();
         }
 
-        return range;
-    },
+        return normalizedRange;
+    }
 
     /**
      * range info
@@ -362,20 +430,20 @@ Calendar.prototype = {
      *  If range[0] > range[1], they will not be reversed.
      * @return {Object}       obj
      */
-    _getRangeInfo: function (range) {
-        range = [
+    _getRangeInfo(range: OptionDataValueDate[]): CalendarParsedDateRangeInfo {
+        const parsedRange = [
             this.getDateInfo(range[0]),
             this.getDateInfo(range[1])
         ];
 
         var reversed;
-        if (range[0].time > range[1].time) {
+        if (parsedRange[0].time > parsedRange[1].time) {
             reversed = true;
-            range.reverse();
+            parsedRange.reverse();
         }
 
-        var allDay = Math.floor(range[1].time / PROXIMATE_ONE_DAY)
-            - Math.floor(range[0].time / PROXIMATE_ONE_DAY) + 1;
+        var allDay = Math.floor(parsedRange[1].time / PROXIMATE_ONE_DAY)
+            - Math.floor(parsedRange[0].time / PROXIMATE_ONE_DAY) + 1;
 
         // Consider case:
         // Firstly set system timezone as "Time Zone: America/Toronto",
@@ -385,36 +453,36 @@ Calendar.prototype = {
         // var allDays = Math.floor(second / ONE_DAY) - Math.floor(first / ONE_DAY) + 1;
         // ```
         // will get wrong result because of DST. So we should fix it.
-        var date = new Date(range[0].time);
+        var date = new Date(parsedRange[0].time);
         var startDateNum = date.getDate();
-        var endDateNum = range[1].date.getDate();
+        var endDateNum = parsedRange[1].date.getDate();
         date.setDate(startDateNum + allDay - 1);
         // The bias can not over a month, so just compare date.
         if (date.getDate() !== endDateNum) {
-            var sign = date.getTime() - range[1].time > 0 ? 1 : -1;
-            while (date.getDate() !== endDateNum && (date.getTime() - range[1].time) * sign > 0) {
+            var sign = date.getTime() - parsedRange[1].time > 0 ? 1 : -1;
+            while (date.getDate() !== endDateNum && (date.getTime() - parsedRange[1].time) * sign > 0) {
                 allDay -= sign;
                 date.setDate(startDateNum + allDay - 1);
             }
         }
 
-        var weeks = Math.floor((allDay + range[0].day + 6) / 7);
+        var weeks = Math.floor((allDay + parsedRange[0].day + 6) / 7);
         var nthWeek = reversed ? -weeks + 1 : weeks - 1;
 
-        reversed && range.reverse();
+        reversed && parsedRange.reverse();
 
         return {
-            range: [range[0].formatedDate, range[1].formatedDate],
-            start: range[0],
-            end: range[1],
+            range: [parsedRange[0].formatedDate, parsedRange[1].formatedDate],
+            start: parsedRange[0],
+            end: parsedRange[1],
             allDay: allDay,
             weeks: weeks,
             // From 0.
             nthWeek: nthWeek,
-            fweek: range[0].day,
-            lweek: range[1].day
+            fweek: parsedRange[0].day,
+            lweek: parsedRange[1].day
         };
-    },
+    }
 
     /**
      * get date by nthWeeks and week day in range
@@ -425,48 +493,44 @@ Calendar.prototype = {
      * @param  {Array} range [d1, d2]
      * @return {Object}
      */
-    _getDateByWeeksAndDay: function (nthWeek, day, range) {
+    private _getDateByWeeksAndDay(nthWeek: number, day: number, range: OptionDataValueDate[]): CalendarParsedDateInfo {
         var rangeInfo = this._getRangeInfo(range);
 
         if (nthWeek > rangeInfo.weeks
             || (nthWeek === 0 && day < rangeInfo.fweek)
             || (nthWeek === rangeInfo.weeks && day > rangeInfo.lweek)
         ) {
-            return false;
+            return null;
         }
 
         var nthDay = (nthWeek - 1) * 7 - rangeInfo.fweek + day;
         var date = new Date(rangeInfo.start.time);
-        date.setDate(rangeInfo.start.d + nthDay);
+        date.setDate(+rangeInfo.start.d + nthDay);
 
         return this.getDateInfo(date);
     }
-};
 
-Calendar.dimensions = Calendar.prototype.dimensions;
+    static create(ecModel: GlobalModel, api: ExtensionAPI) {
+        var calendarList: Calendar[] = [];
 
-Calendar.getDimensionsInfo = Calendar.prototype.getDimensionsInfo;
-
-Calendar.create = function (ecModel, api) {
-    var calendarList = [];
-
-    ecModel.eachComponent('calendar', function (calendarModel) {
-        var calendar = new Calendar(calendarModel, ecModel, api);
-        calendarList.push(calendar);
-        calendarModel.coordinateSystem = calendar;
-    });
+        ecModel.eachComponent('calendar', function (calendarModel: CalendarModel) {
+            var calendar = new Calendar(calendarModel, ecModel, api);
+            calendarList.push(calendar);
+            calendarModel.coordinateSystem = calendar;
+        });
 
-    ecModel.eachSeries(function (calendarSeries) {
-        if (calendarSeries.get('coordinateSystem') === 'calendar') {
-            // Inject coordinate system
-            calendarSeries.coordinateSystem = calendarList[calendarSeries.get('calendarIndex') || 0];
-        }
-    });
-    return calendarList;
-};
+        ecModel.eachSeries(function (calendarSeries: SeriesModel<SeriesOption & SeriesOnCalendarOptionMixin>) {
+            if (calendarSeries.get('coordinateSystem') === 'calendar') {
+                // Inject coordinate system
+                calendarSeries.coordinateSystem = calendarList[calendarSeries.get('calendarIndex') || 0];
+            }
+        });
+        return calendarList;
+    }
+}
 
-function doConvert(methodName, ecModel, finder, value) {
-    var calendarModel = finder.calendarModel;
+function getCoordSys(finder: ParsedModelFinder): Calendar {
+    var calendarModel = finder.calendarModel as CalendarModel;
     var seriesModel = finder.seriesModel;
 
     var coordSys = calendarModel
@@ -475,9 +539,10 @@ function doConvert(methodName, ecModel, finder, value) {
         ? seriesModel.coordinateSystem
         : null;
 
-    return coordSys === this ? coordSys[methodName](value) : null;
+    return coordSys as Calendar;
 }
 
-CoordinateSystem.register('calendar', Calendar);
+
+CoordinateSystemManager.register('calendar', Calendar);
 
 export default Calendar;
\ No newline at end of file
diff --git a/src/coord/calendar/CalendarModel.ts b/src/coord/calendar/CalendarModel.ts
index d30946b..a3c7d40 100644
--- a/src/coord/calendar/CalendarModel.ts
+++ b/src/coord/calendar/CalendarModel.ts
@@ -17,8 +17,6 @@
 * under the License.
 */
 
-// @ts-nocheck
-
 import * as zrUtil from 'zrender/src/core/util';
 import ComponentModel from '../../model/Component';
 import {
@@ -26,17 +24,158 @@ import {
     sizeCalculable,
     mergeLayoutParam
 } from '../../util/layout';
+import Calendar from './Calendar';
+import {
+    ComponentOption,
+    BoxLayoutOptionMixin,
+    LayoutOrient,
+    LineStyleOption,
+    ItemStyleOption,
+    LabelOption,
+    OptionDataValueDate
+} from '../../util/types';
+import GlobalModel from '../../model/Global';
+import Model from '../../model/Model';
+
+export interface CalendarMonthLabelFormatterCallbackParams {
+    nameMap: string
+    yyyy: string
+    yy: string
+    /**
+     * Month string. With 0 prefix.
+     */
+    MM: string
+    /**
+     * Month number
+     */
+    M: number
+}
+
+export interface CalendarYearLabelFormatterCallbackParams {
+    nameMap: string
+    /**
+     * Start year
+     */
+    start: string
+    /**
+     * End year
+     */
+    end: string
+}
 
-var CalendarModel = ComponentModel.extend({
+export interface CalendarOption extends ComponentOption, BoxLayoutOptionMixin {
+    cellSize?: number | 'auto' | (number | 'auto')[]
+    orient?: LayoutOrient
 
-    type: 'calendar',
+    splitLine?: {
+        show?: boolean
+        lineStyle?: LineStyleOption
+    }
 
+    itemStyle?: ItemStyleOption
     /**
-     * @type {module:echarts/coord/calendar/Calendar}
+     * // one year
+     * range: 2017
+     * // one month
+     * range: '2017-02'
+     * //  a range
+     * range: ['2017-01-02', '2017-02-23']
+     * // note: they will be identified as ['2017-01-01', '2017-02-01']
+     * range: ['2017-01', '2017-02']
      */
-    coordinateSystem: null,
+    range?: OptionDataValueDate | (OptionDataValueDate)[]
+
+    dayLabel?: Omit<LabelOption, 'position'> & {
+        /**
+         * First day of week.
+         */
+        firstDay?: number
+
+        /**
+         * Margin between day label and axis line.
+         * Can be percent string of cell size.
+         */
+        margin?: number | string
+
+        /**
+         * Position of week, at the beginning or end of the range.
+         */
+        position?: 'start' | 'end'
 
-    defaultOption: {
+        /**
+         * Week text content, defaults to 'en'; It supports Chinese, English, and custom; index 0 always means Sunday
+         * en: shortcut to English  ['S', 'M', 'T', 'W', 'T', 'F', 'S']
+         * cn: shortcut to Chinese ['日', '一', '二', '三', '四', '五', '六']
+         */
+        nameMap?: 'en' | 'cn' | string[]
+    }
+
+    monthLabel?: Omit<LabelOption, 'position'> & {
+        /**
+         * Margin between month label and axis line.
+         */
+        margin?: number
+
+        /**
+         * Position of month label, at the beginning or end of the range.
+         */
+        position?: 'start' | 'end'
+
+        /**
+         * Month text content, defaults to 'en'; It supports Chinese, English, and custom; Index 0 always means Jan;
+         */
+        nameMap?: 'en' | 'cn' | string[]
+
+        formatter?: string | ((params: CalendarMonthLabelFormatterCallbackParams) => string)
+    }
+
+    yearLabel?: Omit<LabelOption, 'position'> & {
+        /**
+         * Margin between year label and axis line.
+         */
+        margin?: number
+
+        /**
+         * Position of year label, at the beginning or end of the range.
+         */
+        position?: 'top' | 'bottom' | 'left' | 'right'
+
+        formatter?: string | ((params: CalendarYearLabelFormatterCallbackParams) => string)
+    }
+}
+
+class CalendarModel extends ComponentModel<CalendarOption> {
+    static type = 'calendar'
+    type = CalendarModel.type
+
+    coordinateSystem: Calendar
+
+    /**
+     * @override
+     */
+    init(option: CalendarOption, parentModel: Model, ecModel: GlobalModel) {
+        var inputPositionParams = getLayoutParams(option);
+
+        super.init.apply(this, arguments as any);
+
+        mergeAndNormalizeLayoutParams(option, inputPositionParams);
+    }
+
+    /**
+     * @override
+     */
+    mergeOption(option: CalendarOption) {
+        super.mergeOption.apply(this, arguments as any);
+
+        mergeAndNormalizeLayoutParams(this.option, option);
+    }
+
+    getCellSize() {
+        // Has been normalized
+        return this.option.cellSize as (number | 'auto')[];
+    }
+
+    static defaultOption: CalendarOption = {
         zlevel: 0,
         z: 2,
         left: 80,
@@ -68,7 +207,6 @@ var CalendarModel = ComponentModel.extend({
         dayLabel: {
             show: true,
 
-            // a week first day
             firstDay: 0,
 
             // start end
@@ -108,48 +246,34 @@ var CalendarModel = ComponentModel.extend({
             fontWeight: 'bolder',
             fontSize: 20
         }
-    },
-
-    /**
-     * @override
-     */
-    init: function (option, parentModel, ecModel, extraOpt) {
-        var inputPositionParams = getLayoutParams(option);
-
-        CalendarModel.superApply(this, 'init', arguments);
-
-        mergeAndNormalizeLayoutParams(option, inputPositionParams);
-    },
-
-    /**
-     * @override
-     */
-    mergeOption: function (option, extraOpt) {
-        CalendarModel.superApply(this, 'mergeOption', arguments);
-
-        mergeAndNormalizeLayoutParams(this.option, option);
     }
-});
+}
 
-function mergeAndNormalizeLayoutParams(target, raw) {
+
+function mergeAndNormalizeLayoutParams(target: CalendarOption, raw: BoxLayoutOptionMixin) {
     // Normalize cellSize
     var cellSize = target.cellSize;
+    var cellSizeArr: (number | 'auto')[];
 
     if (!zrUtil.isArray(cellSize)) {
-        cellSize = target.cellSize = [cellSize, cellSize];
+        cellSizeArr = target.cellSize = [cellSize, cellSize];
+    }
+    else {
+        cellSizeArr = cellSize;
     }
-    else if (cellSize.length === 1) {
-        cellSize[1] = cellSize[0];
+
+    if (cellSizeArr.length === 1) {
+        cellSizeArr[1] = cellSizeArr[0];
     }
 
     var ignoreSize = zrUtil.map([0, 1], function (hvIdx) {
-        // If user have set `width` or both `left` and `right`, cellSize
+        // If user have set `width` or both `left` and `right`, cellSizeArr
         // will be automatically set to 'auto', otherwise the default
-        // setting of cellSize will make `width` setting not work.
+        // setting of cellSizeArr will make `width` setting not work.
         if (sizeCalculable(raw, hvIdx)) {
-            cellSize[hvIdx] = 'auto';
+            cellSizeArr[hvIdx] = 'auto';
         }
-        return cellSize[hvIdx] != null && cellSize[hvIdx] !== 'auto';
+        return cellSizeArr[hvIdx] != null && cellSizeArr[hvIdx] !== 'auto';
     });
 
     mergeLayoutParam(target, raw, {
@@ -157,4 +281,6 @@ function mergeAndNormalizeLayoutParams(target, raw) {
     });
 }
 
+ComponentModel.registerClass(CalendarModel);
+
 export default CalendarModel;
diff --git a/src/coord/calendar/prepareCustom.ts b/src/coord/calendar/prepareCustom.ts
index 56f9574..a217497 100644
--- a/src/coord/calendar/prepareCustom.ts
+++ b/src/coord/calendar/prepareCustom.ts
@@ -17,9 +17,10 @@
 * under the License.
 */
 
-// @ts-nocheck
+import Calendar from './Calendar';
+import { OptionDataValueDate } from '../../util/types';
 
-export default function (coordSys) {
+export default function (coordSys: Calendar) {
     var rect = coordSys.getRect();
     var rangeInfo = coordSys.getRangeInfo();
 
@@ -40,7 +41,7 @@ export default function (coordSys) {
             }
         },
         api: {
-            coord: function (data, clamp) {
+            coord: function (data: OptionDataValueDate, clamp?: boolean) {
                 return coordSys.dataToPoint(data, clamp);
             }
         }
diff --git a/src/echarts.ts b/src/echarts.ts
index d31a78a..fb5ba37 100644
--- a/src/echarts.ts
+++ b/src/echarts.ts
@@ -1023,10 +1023,10 @@ class ECharts {
             return;
         }
 
-        var silent = (opt as any).silent;
+        var silent = opt.silent;
         doDispatchAction.call(this, payload, silent);
 
-        var flush = (opt as any).flush;
+        var flush = opt.flush;
         if (flush) {
             this._zr.flush();
         }
diff --git a/src/util/types.ts b/src/util/types.ts
index 12579f8..50fbfe8 100644
--- a/src/util/types.ts
+++ b/src/util/types.ts
@@ -494,7 +494,7 @@ export type MediaUnit = {
 export type ComponentLayoutMode = {
     // Only support 'box' now.
     type: 'box',
-    ignoreSize?: boolean | [boolean, boolean]
+    ignoreSize?: boolean | boolean[]
 };
 /******************* Mixins for Common Option Properties   ********************** */
 export interface ColorPaletteOptionMixin {


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