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

[incubator-echarts] branch typescript updated: ts: add types in util folder

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 2adc5b8  ts: add types in util folder
2adc5b8 is described below

commit 2adc5b857e824b976ffa74dd600be8656dba176d
Author: pissang <bm...@gmail.com>
AuthorDate: Tue Feb 18 22:13:54 2020 +0800

    ts: add types in util folder
---
 src/chart/pie/PieSeries.ts |   4 +-
 src/util/KDTree.ts         | 390 ++++++++++++++++++++++++---------------------
 src/util/animation.ts      |   8 +-
 src/util/format.ts         |  90 +++++------
 src/util/graphic.ts        |   2 +-
 src/util/layout.ts         | 192 ++++++++++++----------
 src/util/number.ts         | 120 ++++++--------
 src/util/quickSelect.ts    |  29 ++--
 src/util/shape/sausage.ts  |   4 +-
 src/util/symbol.ts         | 141 ++++++++--------
 src/util/throttle.ts       |  22 ++-
 src/util/types.ts          |  16 +-
 12 files changed, 522 insertions(+), 496 deletions(-)

diff --git a/src/chart/pie/PieSeries.ts b/src/chart/pie/PieSeries.ts
index b7217fd..a5db3fa 100644
--- a/src/chart/pie/PieSeries.ts
+++ b/src/chart/pie/PieSeries.ts
@@ -98,8 +98,8 @@ class PieSeries extends SeriesModel {
         var params = super.getDataParams(dataIndex);
         // FIXME toFixed?
 
-        var valueList = [] as ParsedDataValue[];
-        data.each(data.mapDimension('value'), function (value) {
+        var valueList: number[] = [];
+        data.each(data.mapDimension('value'), function (value: number) {
             valueList.push(value);
         });
 
diff --git a/src/util/KDTree.ts b/src/util/KDTree.ts
index 12defbd..ce469e0 100644
--- a/src/util/KDTree.ts
+++ b/src/util/KDTree.ts
@@ -17,16 +17,25 @@
 * under the License.
 */
 
-// @ts-nocheck
-
 import quickSelect from './quickSelect';
+import { VectorArray } from 'zrender/src/core/vector';
+
+type KDTreePoint = {
+    array: VectorArray
+}
+
+class KDTreeNode<T> {
+
+    left: KDTreeNode<T>
+    right: KDTreeNode<T>
 
-function Node(axis, data) {
-    this.left = null;
-    this.right = null;
-    this.axis = axis;
+    axis: number
+    data: T
 
-    this.data = data;
+    constructor(axis: number, data: T) {
+        this.axis = axis;
+        this.data = data;
+    }
 }
 
 /**
@@ -38,222 +47,241 @@ function Node(axis, data) {
  *        Point dimension.
  *        Default will use the first point's length as dimensiont
  */
-var KDTree = function (points, dimension) {
-    if (!points.length) {
-        return;
-    }
 
-    if (!dimension) {
-        dimension = points[0].array.length;
-    }
-    this.dimension = dimension;
-    this.root = this._buildTree(points, 0, points.length - 1, 0);
+class KDTree<T extends KDTreePoint> {
+
+    dimension: number
+    root: KDTreeNode<T>
 
     // Use one stack to avoid allocation
     // each time searching the nearest point
-    this._stack = [];
+    private _stack: KDTreeNode<T>[] = []
     // Again avoid allocating a new array
     // each time searching nearest N points
-    this._nearstNList = [];
-};
+    private _nearstNList: {
+        dist: number,
+        node: KDTreeNode<T>
+    }[] = []
 
-/**
- * Resursively build the tree
- */
-KDTree.prototype._buildTree = function (points, left, right, axis) {
-    if (right < left) {
-        return null;
-    }
+    constructor(points: T[], dimension?: number) {
+        if (!points.length) {
+            return;
+        }
 
-    var medianIndex = Math.floor((left + right) / 2);
-    medianIndex = quickSelect(
-        points, left, right, medianIndex,
-        function (a, b) {
-            return a.array[axis] - b.array[axis];
+        if (!dimension) {
+            dimension = points[0].array.length;
         }
-    );
-    var median = points[medianIndex];
+        this.dimension = dimension;
+        this.root = this._buildTree(points, 0, points.length - 1, 0);
+    }
 
-    var node = new Node(axis, median);
+    /**
+     * Resursively build the tree
+     */
+    private _buildTree(points: T[], left: number, right: number, axis: number): KDTreeNode<T> {
+        if (right < left) {
+            return null;
+        }
 
-    axis = (axis + 1) % this.dimension;
-    if (right > left) {
-        node.left = this._buildTree(points, left, medianIndex - 1, axis);
-        node.right = this._buildTree(points, medianIndex + 1, right, axis);
-    }
+        var medianIndex = Math.floor((left + right) / 2);
+        medianIndex = quickSelect(
+            points, left, right, medianIndex,
+            function (a: T, b: T) {
+                return a.array[axis] - b.array[axis];
+            }
+        );
+        var median = points[medianIndex];
 
-    return node;
-};
+        var node = new KDTreeNode(axis, median);
 
-/**
- * Find nearest point
- * @param  {Array} target Target point
- * @param  {Function} squaredDistance Squared distance function
- * @return {Array} Nearest point
- */
-KDTree.prototype.nearest = function (target, squaredDistance) {
-    var curr = this.root;
-    var stack = this._stack;
-    var idx = 0;
-    var minDist = Infinity;
-    var nearestNode = null;
-    if (curr.data !== target) {
-        minDist = squaredDistance(curr.data, target);
-        nearestNode = curr;
-    }
+        axis = (axis + 1) % this.dimension;
+        if (right > left) {
+            node.left = this._buildTree(points, left, medianIndex - 1, axis);
+            node.right = this._buildTree(points, medianIndex + 1, right, axis);
+        }
 
-    if (target.array[curr.axis] < curr.data.array[curr.axis]) {
-        // Left first
-        curr.right && (stack[idx++] = curr.right);
-        curr.left && (stack[idx++] = curr.left);
-    }
-    else {
-        // Right first
-        curr.left && (stack[idx++] = curr.left);
-        curr.right && (stack[idx++] = curr.right);
-    }
+        return node;
+    };
 
-    while (idx--) {
-        curr = stack[idx];
-        var currDist = target.array[curr.axis] - curr.data.array[curr.axis];
-        var isLeft = currDist < 0;
-        var needsCheckOtherSide = false;
-        currDist = currDist * currDist;
-        // Intersecting right hyperplane with minDist hypersphere
-        if (currDist < minDist) {
-            currDist = squaredDistance(curr.data, target);
-            if (currDist < minDist && curr.data !== target) {
-                minDist = currDist;
-                nearestNode = curr;
-            }
-            needsCheckOtherSide = true;
+    /**
+     * Find nearest point
+     * @param  target Target point
+     * @param  squaredDistance Squared distance function
+     * @return Nearest point
+     */
+    nearest(target: T, squaredDistance: (a: T, b: T) => number) {
+        var curr = this.root;
+        var stack = this._stack;
+        var idx = 0;
+        var minDist = Infinity;
+        var nearestNode = null;
+        if (curr.data !== target) {
+            minDist = squaredDistance(curr.data, target);
+            nearestNode = curr;
         }
-        if (isLeft) {
-            if (needsCheckOtherSide) {
-                curr.right && (stack[idx++] = curr.right);
-            }
-            // Search in the left area
+
+        if (target.array[curr.axis] < curr.data.array[curr.axis]) {
+            // Left first
+            curr.right && (stack[idx++] = curr.right);
             curr.left && (stack[idx++] = curr.left);
         }
         else {
-            if (needsCheckOtherSide) {
+            // Right first
+            curr.left && (stack[idx++] = curr.left);
+            curr.right && (stack[idx++] = curr.right);
+        }
+
+        while (idx--) {
+            curr = stack[idx];
+            var currDist = target.array[curr.axis] - curr.data.array[curr.axis];
+            var isLeft = currDist < 0;
+            var needsCheckOtherSide = false;
+            currDist = currDist * currDist;
+            // Intersecting right hyperplane with minDist hypersphere
+            if (currDist < minDist) {
+                currDist = squaredDistance(curr.data, target);
+                if (currDist < minDist && curr.data !== target) {
+                    minDist = currDist;
+                    nearestNode = curr;
+                }
+                needsCheckOtherSide = true;
+            }
+            if (isLeft) {
+                if (needsCheckOtherSide) {
+                    curr.right && (stack[idx++] = curr.right);
+                }
+                // Search in the left area
                 curr.left && (stack[idx++] = curr.left);
             }
-            // Search the right area
-            curr.right && (stack[idx++] = curr.right);
+            else {
+                if (needsCheckOtherSide) {
+                    curr.left && (stack[idx++] = curr.left);
+                }
+                // Search the right area
+                curr.right && (stack[idx++] = curr.right);
+            }
         }
-    }
 
-    return nearestNode.data;
-};
+        return nearestNode.data;
+    };
 
-KDTree.prototype._addNearest = function (found, dist, node) {
-    var nearestNList = this._nearstNList;
+    _addNearest(found: number, dist: number, node: KDTreeNode<T>) {
+        var nearestNList = this._nearstNList;
 
-    // Insert to the right position
-    // Sort from small to large
-    for (var i = found - 1; i > 0; i--) {
-        if (dist >= nearestNList[i - 1].dist) {
-            break;
-        }
-        else {
-            nearestNList[i].dist = nearestNList[i - 1].dist;
-            nearestNList[i].node = nearestNList[i - 1].node;
+        // Insert to the right position
+        // Sort from small to large
+        for (var i = found - 1; i > 0; i--) {
+            if (dist >= nearestNList[i - 1].dist) {
+                break;
+            }
+            else {
+                nearestNList[i].dist = nearestNList[i - 1].dist;
+                nearestNList[i].node = nearestNList[i - 1].node;
+            }
         }
-    }
 
-    nearestNList[i].dist = dist;
-    nearestNList[i].node = node;
-};
+        nearestNList[i].dist = dist;
+        nearestNList[i].node = node;
+    };
 
-/**
- * Find nearest N points
- * @param  {Array} target Target point
- * @param  {number} N
- * @param  {Function} squaredDistance Squared distance function
- * @param  {Array} [output] Output nearest N points
- */
-KDTree.prototype.nearestN = function (target, N, squaredDistance, output) {
-    if (N <= 0) {
-        output.length = 0;
-        return output;
-    }
+    /**
+     * Find nearest N points
+     * @param  target Target point
+     * @param  N
+     * @param  squaredDistance Squared distance function
+     * @param  output Output nearest N points
+     */
+    nearestN(
+        target: T,
+        N: number,
+        squaredDistance: (a: T, b: T) => number,
+        output: T[]
+    ) {
+        if (N <= 0) {
+            output.length = 0;
+            return output;
+        }
 
-    var curr = this.root;
-    var stack = this._stack;
-    var idx = 0;
+        var curr = this.root;
+        var stack = this._stack;
+        var idx = 0;
 
-    var nearestNList = this._nearstNList;
-    for (var i = 0; i < N; i++) {
-        // Allocate
-        if (!nearestNList[i]) {
-            nearestNList[i] = {};
+        var nearestNList = this._nearstNList;
+        for (var i = 0; i < N; i++) {
+            // Allocate
+            if (!nearestNList[i]) {
+                nearestNList[i] = {
+                    dist: 0, node: null
+                };
+            }
+            nearestNList[i].dist = 0;
+            nearestNList[i].node = null;
         }
-        nearestNList[i].dist = 0;
-        nearestNList[i].node = null;
-    }
-    var currDist = squaredDistance(curr.data, target);
+        var currDist = squaredDistance(curr.data, target);
 
-    var found = 0;
-    if (curr.data !== target) {
-        found++;
-        this._addNearest(found, currDist, curr);
-    }
+        var found = 0;
+        if (curr.data !== target) {
+            found++;
+            this._addNearest(found, currDist, curr);
+        }
 
-    if (target.array[curr.axis] < curr.data.array[curr.axis]) {
-        // Left first
-        curr.right && (stack[idx++] = curr.right);
-        curr.left && (stack[idx++] = curr.left);
-    }
-    else {
-        // Right first
-        curr.left && (stack[idx++] = curr.left);
-        curr.right && (stack[idx++] = curr.right);
-    }
+        if (target.array[curr.axis] < curr.data.array[curr.axis]) {
+            // Left first
+            curr.right && (stack[idx++] = curr.right);
+            curr.left && (stack[idx++] = curr.left);
+        }
+        else {
+            // Right first
+            curr.left && (stack[idx++] = curr.left);
+            curr.right && (stack[idx++] = curr.right);
+        }
 
-    while (idx--) {
-        curr = stack[idx];
-        var currDist = target.array[curr.axis] - curr.data.array[curr.axis];
-        var isLeft = currDist < 0;
-        var needsCheckOtherSide = false;
-        currDist = currDist * currDist;
-        // Intersecting right hyperplane with minDist hypersphere
-        if (found < N || currDist < nearestNList[found - 1].dist) {
-            currDist = squaredDistance(curr.data, target);
-            if (
-                (found < N || currDist < nearestNList[found - 1].dist)
-                && curr.data !== target
-            ) {
-                if (found < N) {
-                    found++;
+        while (idx--) {
+            curr = stack[idx];
+            var currDist = target.array[curr.axis] - curr.data.array[curr.axis];
+            var isLeft = currDist < 0;
+            var needsCheckOtherSide = false;
+            currDist = currDist * currDist;
+            // Intersecting right hyperplane with minDist hypersphere
+            if (found < N || currDist < nearestNList[found - 1].dist) {
+                currDist = squaredDistance(curr.data, target);
+                if (
+                    (found < N || currDist < nearestNList[found - 1].dist)
+                    && curr.data !== target
+                ) {
+                    if (found < N) {
+                        found++;
+                    }
+                    this._addNearest(found, currDist, curr);
                 }
-                this._addNearest(found, currDist, curr);
+                needsCheckOtherSide = true;
             }
-            needsCheckOtherSide = true;
-        }
-        if (isLeft) {
-            if (needsCheckOtherSide) {
+            if (isLeft) {
+                if (needsCheckOtherSide) {
+                    curr.right && (stack[idx++] = curr.right);
+                }
+                // Search in the left area
+                curr.left && (stack[idx++] = curr.left);
+            }
+            else {
+                if (needsCheckOtherSide) {
+                    curr.left && (stack[idx++] = curr.left);
+                }
+                // Search the right area
                 curr.right && (stack[idx++] = curr.right);
             }
-            // Search in the left area
-            curr.left && (stack[idx++] = curr.left);
         }
-        else {
-            if (needsCheckOtherSide) {
-                curr.left && (stack[idx++] = curr.left);
-            }
-            // Search the right area
-            curr.right && (stack[idx++] = curr.right);
+
+        // Copy to output
+        for (var i = 0; i < found; i++) {
+            output[i] = nearestNList[i].node.data;
         }
-    }
+        output.length = found;
 
-    // Copy to output
-    for (var i = 0; i < found; i++) {
-        output[i] = nearestNList[i].node.data;
+        return output;
     }
-    output.length = found;
 
-    return output;
-};
+}
+
 
 export default KDTree;
\ No newline at end of file
diff --git a/src/util/animation.ts b/src/util/animation.ts
index 522b61c..08275c8 100644
--- a/src/util/animation.ts
+++ b/src/util/animation.ts
@@ -20,6 +20,8 @@
 // @ts-nocheck
 
 import * as zrUtil from 'zrender/src/core/util';
+import Element, { ElementProps } from 'zrender/src/Element';
+import { easingType } from 'zrender/src/animation/easing';
 
 /**
  * @param {number} [time=500] Time in ms
@@ -62,7 +64,7 @@ export function createWrap() {
          *     add(el, target, time);
          *     add(el, target);
          */
-        add: function (el, target, time, delay, easing) {
+        add: function (el: Element, target: ElementProps, time?: number, delay?: number | easingType, easing?: easingType) {
             if (zrUtil.isString(delay)) {
                 easing = delay;
                 delay = 0;
@@ -83,10 +85,8 @@ export function createWrap() {
         /**
          * Only execute when animation finished. Will not execute when any
          * of 'stop' or 'stopAnimation' called.
-         *
-         * @param {Function} callback
          */
-        done: function (callback) {
+        done: function (callback: () => void) {
             doneCallback = callback;
             return this;
         },
diff --git a/src/util/format.ts b/src/util/format.ts
index 7f6ade2..c669d12 100644
--- a/src/util/format.ts
+++ b/src/util/format.ts
@@ -17,34 +17,27 @@
 * under the License.
 */
 
-// @ts-nocheck
-
 import * as zrUtil from 'zrender/src/core/util';
 import * as textContain from 'zrender/src/contain/text';
 import * as numberUtil from './number';
 import {TooltipRenderMode} from './types';
+import { Dictionary } from 'zrender/src/core/types';
+import Style, { StyleProps } from 'zrender/src/graphic/Style';
 // import Text from 'zrender/src/graphic/Text';
 
 /**
  * Add a comma each three digit.
- * @param {string|number} x
- * @return {string}
  */
-export function addCommas(x) {
-    if (isNaN(x)) {
+export function addCommas(x: string | number): string {
+    if (isNaN(x as number)) {
         return '-';
     }
-    x = (x + '').split('.');
-    return x[0].replace(/(\d{1,3})(?=(?:\d{3})+(?!\d))/g, '$1,')
-            + (x.length > 1 ? ('.' + x[1]) : '');
+    const parts = (x + '').split('.');
+    return parts[0].replace(/(\d{1,3})(?=(?:\d{3})+(?!\d))/g, '$1,')
+            + (parts.length > 1 ? ('.' + parts[1]) : '');
 }
 
-/**
- * @param {string} str
- * @param {boolean} [upperCaseFirst=false]
- * @return {string} str
- */
-export function toCamelCase(str, upperCaseFirst) {
+export function toCamelCase(str: string, upperCaseFirst: boolean): string {
     str = (str || '').toLowerCase().replace(/-(.)/g, function (match, group1) {
         return group1.toUpperCase();
     });
@@ -60,7 +53,7 @@ export var normalizeCssArray = zrUtil.normalizeCssArray;
 
 
 var replaceReg = /([&<>"'])/g;
-var replaceMap = {
+var replaceMap: Dictionary<string> = {
     '&': '&amp;',
     '<': '&lt;',
     '>': '&gt;',
@@ -68,7 +61,7 @@ var replaceMap = {
     '\'': '&#39;'
 };
 
-export function encodeHTML(source) {
+export function encodeHTML(source: string): string {
     return source == null
         ? ''
         : (source + '').replace(replaceReg, function (str, c) {
@@ -82,7 +75,7 @@ var wrapVar = function (varName: string, seriesIdx?: number): string {
     return '{' + varName + (seriesIdx == null ? '' : seriesIdx) + '}';
 };
 
-export interface TplFormatterParam {
+export interface TplFormatterParam extends Dictionary<any> {
     // Param name list for mapping `a`, `b`, `c`, `d`, `e`
     $vars: string[];
 }
@@ -98,7 +91,7 @@ export function formatTpl(
     if (!zrUtil.isArray(paramsList)) {
         paramsList = [paramsList];
     }
-    var seriesLen = (paramsList as any).length;
+    var seriesLen = paramsList.length;
     if (!seriesLen) {
         return '';
     }
@@ -123,13 +116,8 @@ export function formatTpl(
 
 /**
  * simple Template formatter
- *
- * @param {string} tpl
- * @param {Object} param
- * @param {boolean} [encode=false]
- * @return {string}
  */
-export function formatTplSimple(tpl, param, encode) {
+export function formatTplSimple(tpl: string, param: Dictionary<any>, encode?: boolean) {
     zrUtil.each(param, function (value, key) {
         tpl = tpl.replace(
             '{' + key + '}',
@@ -193,7 +181,7 @@ export function getTooltipMarker(opt: string | GetTooltipMarkerOpt, extraCssText
     }
 }
 
-function pad(str, len) {
+function pad(str: string, len: number): string {
     str += '';
     return '0000'.substr(0, len - str.length) + str;
 }
@@ -208,7 +196,7 @@ function pad(str, len) {
  *           and `module:echarts/util/number#parseDate`.
  * @inner
  */
-export function formatTime(tpl, value, isUTC?) {
+export function formatTime(tpl: string, value: number, isUTC?: boolean) {
     if (tpl === 'week'
         || tpl === 'month'
         || tpl === 'quarter'
@@ -220,18 +208,18 @@ export function formatTime(tpl, value, isUTC?) {
 
     var date = numberUtil.parseDate(value);
     var utc = isUTC ? 'UTC' : '';
-    var y = date['get' + utc + 'FullYear']();
-    var M = date['get' + utc + 'Month']() + 1;
-    var d = date['get' + utc + 'Date']();
-    var h = date['get' + utc + 'Hours']();
-    var m = date['get' + utc + 'Minutes']();
-    var s = date['get' + utc + 'Seconds']();
-    var S = date['get' + utc + 'Milliseconds']();
+    var y = (date as any)['get' + utc + 'FullYear']();
+    var M = (date as any)['get' + utc + 'Month']() + 1;
+    var d = (date as any)['get' + utc + 'Date']();
+    var h = (date as any)['get' + utc + 'Hours']();
+    var m = (date as any)['get' + utc + 'Minutes']();
+    var s = (date as any)['get' + utc + 'Seconds']();
+    var S = (date as any)['get' + utc + 'Milliseconds']();
 
     tpl = tpl.replace('MM', pad(M, 2))
         .replace('M', M)
         .replace('yyyy', y)
-        .replace('yy', y % 100)
+        .replace('yy', y % 100 + '')
         .replace('dd', pad(d, 2))
         .replace('d', d)
         .replace('hh', pad(h, 2))
@@ -250,32 +238,19 @@ export function formatTime(tpl, value, isUTC?) {
  * @param {string} str
  * @return {string}
  */
-export function capitalFirst(str) {
+export function capitalFirst(str: string): string {
     return str ? str.charAt(0).toUpperCase() + str.substr(1) : str;
 }
 
 export var truncateText = textContain.truncateText;
 
-/**
- * @public
- * @param {Object} opt
- * @param {string} opt.text
- * @param {string} opt.font
- * @param {string} [opt.textAlign='left']
- * @param {string} [opt.textVerticalAlign='top']
- * @param {Array.<number>} [opt.textPadding]
- * @param {number} [opt.textLineHeight]
- * @param {Object} [opt.rich]
- * @param {Object} [opt.truncate]
- * @return {Object} {x, y, width, height, lineHeight}
- */
-export function getTextBoundingRect(opt) {
+export function getTextBoundingRect(opt: StyleProps): ReturnType<typeof textContain.getBoundingRect> {
     return textContain.getBoundingRect(
         opt.text,
         opt.font,
         opt.textAlign,
         opt.textVerticalAlign,
-        opt.textPadding,
+        opt.textPadding as number[],
         opt.textLineHeight,
         opt.rich,
         opt.truncate
@@ -289,9 +264,16 @@ export function getTextBoundingRect(opt) {
  * But deprecated this interface. Please use `getTextBoundingRect` instead.
  */
 export function getTextRect(
-    text, font, textAlign, textVerticalAlign, textPadding, rich, truncate, textLineHeight
-) {
+    text: StyleProps['text'],
+    font: StyleProps['font'],
+    textAlign: StyleProps['textAlign'],
+    textVerticalAlign: StyleProps['textVerticalAlign'],
+    textPadding: StyleProps['textPadding'],
+    rich: StyleProps['rich'],
+    truncate: StyleProps['truncate'],
+    textLineHeight: number
+): ReturnType<typeof textContain.getBoundingRect> {
     return textContain.getBoundingRect(
-        text, font, textAlign, textVerticalAlign, textPadding, textLineHeight, rich, truncate
+        text, font, textAlign, textVerticalAlign, textPadding as number[], textLineHeight, rich, truncate
     );
 }
diff --git a/src/util/graphic.ts b/src/util/graphic.ts
index 7ecd757..5f108de 100644
--- a/src/util/graphic.ts
+++ b/src/util/graphic.ts
@@ -233,7 +233,7 @@ export function makePath(
  * @param layout 'center' or 'cover'. Default to be 'cover'
  */
 export function makeImage(
-    imageUrl: ImageLike,
+    imageUrl: string,
     rect: RectLike,
     layout?: 'center' | 'cover'
 ) {
diff --git a/src/util/layout.ts b/src/util/layout.ts
index b585eba..e5f1985 100644
--- a/src/util/layout.ts
+++ b/src/util/layout.ts
@@ -17,33 +17,50 @@
 * under the License.
 */
 
-// @ts-nocheck
-
 // Layout helpers for each component positioning
 
 import * as zrUtil from 'zrender/src/core/util';
-import BoundingRect from 'zrender/src/core/BoundingRect';
+import BoundingRect, { RectLike } from 'zrender/src/core/BoundingRect';
 import {parsePercent} from './number';
 import * as formatUtil from './format';
+import { BoxLayoutOptionMixin, ECUnitOption } from './types';
+import { Group } from 'zrender/src/export';
+import Element from 'zrender/src/Element';
+import { Dictionary } from 'zrender/src/core/types';
+
+const each = zrUtil.each;
 
-var each = zrUtil.each;
+interface LayoutRect extends BoundingRect {
+    margin: number[]
+}
+
+export interface NewlineElement extends Element {
+    newline: boolean
+}
 
+type BoxLayoutKeys = keyof BoxLayoutOptionMixin
 /**
  * @public
  */
-export var LOCATION_PARAMS = [
+export const LOCATION_PARAMS = [
     'left', 'right', 'top', 'bottom', 'width', 'height'
-];
+] as const;
 
 /**
  * @public
  */
-export var HV_NAMES = [
+export const HV_NAMES = [
     ['width', 'left', 'right'],
     ['height', 'top', 'bottom']
-];
-
-function boxLayout(orient, group, gap, maxWidth, maxHeight) {
+] as const;
+
+function boxLayout(
+    orient: 'horizontal' | 'vertical',
+    group: Group,
+    gap: number,
+    maxWidth?: number,
+    maxHeight?: number
+) {
     var x = 0;
     var y = 0;
 
@@ -68,7 +85,7 @@ function boxLayout(orient, group, gap, maxWidth, maxHeight) {
             nextX = x + moveX;
             // Wrap when width exceeds maxWidth or meet a `newline` group
             // FIXME compare before adding gap?
-            if (nextX > maxWidth || child.newline) {
+            if (nextX > maxWidth || (child as NewlineElement).newline) {
                 x = 0;
                 nextX = moveX;
                 y += currentLineMaxSize + gap;
@@ -83,7 +100,7 @@ function boxLayout(orient, group, gap, maxWidth, maxHeight) {
             var moveY = rect.height + (nextChildRect ? (-nextChildRect.y + rect.y) : 0);
             nextY = y + moveY;
             // Wrap when width exceeds maxHeight or meet a `newline` group
-            if (nextY > maxHeight || child.newline) {
+            if (nextY > maxHeight || (child as NewlineElement).newline) {
                 x += currentLineMaxSize + gap;
                 y = 0;
                 nextY = moveY;
@@ -94,7 +111,7 @@ function boxLayout(orient, group, gap, maxWidth, maxHeight) {
             }
         }
 
-        if (child.newline) {
+        if ((child as NewlineElement).newline) {
             return;
         }
 
@@ -140,17 +157,17 @@ export var hbox = zrUtil.curry(boxLayout, 'horizontal');
  * the width would be as long as possible.
  * If y or y2 is not specified or 'middle' 'top' 'bottom',
  * the height would be as long as possible.
- *
- * @param {Object} positionInfo
- * @param {number|string} [positionInfo.x]
- * @param {number|string} [positionInfo.y]
- * @param {number|string} [positionInfo.x2]
- * @param {number|string} [positionInfo.y2]
- * @param {Object} containerRect {width, height}
- * @param {string|number} margin
- * @return {Object} {width, height}
  */
-export function getAvailableSize(positionInfo, containerRect, margin) {
+export function getAvailableSize(
+    positionInfo: {
+        x: number | string
+        y: number | string
+        x2: number | string
+        y2: number | string
+    },
+    containerRect: RectLike,
+    margin: number[] | number
+) {
     var containerWidth = containerRect.width;
     var containerHeight = containerRect.height;
 
@@ -159,10 +176,10 @@ export function getAvailableSize(positionInfo, containerRect, margin) {
     var x2 = parsePercent(positionInfo.x2, containerWidth);
     var y2 = parsePercent(positionInfo.y2, containerHeight);
 
-    (isNaN(x) || isNaN(parseFloat(positionInfo.x))) && (x = 0);
-    (isNaN(x2) || isNaN(parseFloat(positionInfo.x2))) && (x2 = containerWidth);
-    (isNaN(y) || isNaN(parseFloat(positionInfo.y))) && (y = 0);
-    (isNaN(y2) || isNaN(parseFloat(positionInfo.y2))) && (y2 = containerHeight);
+    (isNaN(x) || isNaN(parseFloat(positionInfo.x as string))) && (x = 0);
+    (isNaN(x2) || isNaN(parseFloat(positionInfo.x2 as string))) && (x2 = containerWidth);
+    (isNaN(y) || isNaN(parseFloat(positionInfo.y as string))) && (y = 0);
+    (isNaN(y2) || isNaN(parseFloat(positionInfo.y2 as string))) && (y2 = containerHeight);
 
     margin = formatUtil.normalizeCssArray(margin || 0);
 
@@ -174,23 +191,14 @@ export function getAvailableSize(positionInfo, containerRect, margin) {
 
 /**
  * Parse position info.
- *
- * @param {Object} positionInfo
- * @param {number|string} [positionInfo.left]
- * @param {number|string} [positionInfo.top]
- * @param {number|string} [positionInfo.right]
- * @param {number|string} [positionInfo.bottom]
- * @param {number|string} [positionInfo.width]
- * @param {number|string} [positionInfo.height]
- * @param {number|string} [positionInfo.aspect] Aspect is width / height
- * @param {Object} containerRect
- * @param {string|number} [margin]
- *
- * @return {module:zrender/core/BoundingRect}
  */
 export function getLayoutRect(
-    positionInfo, containerRect, margin
-) {
+    positionInfo: BoxLayoutOptionMixin & {
+        aspect?: number // aspect is width / height
+    },
+    containerRect: RectLike,
+    margin?: number | number[]
+): LayoutRect {
     margin = formatUtil.normalizeCssArray(margin || 0);
 
     var containerWidth = containerRect.width;
@@ -279,7 +287,7 @@ export function getLayoutRect(
         height = containerHeight - verticalMargin - top - (bottom || 0);
     }
 
-    var rect = new BoundingRect(left + margin[3], top + margin[0], width, height);
+    var rect = new BoundingRect(left + margin[3], top + margin[0], width, height) as LayoutRect;
     rect.margin = margin;
     return rect;
 }
@@ -300,19 +308,19 @@ export function getLayoutRect(
  *
  * If be called repeatly with the same input el, the same result will be gotten.
  *
- * @param {module:zrender/Element} el Should have `getBoundingRect` method.
- * @param {Object} positionInfo
- * @param {number|string} [positionInfo.left]
- * @param {number|string} [positionInfo.top]
- * @param {number|string} [positionInfo.right]
- * @param {number|string} [positionInfo.bottom]
- * @param {number|string} [positionInfo.width] Only for opt.boundingModel: 'raw'
- * @param {number|string} [positionInfo.height] Only for opt.boundingModel: 'raw'
- * @param {Object} containerRect
- * @param {string|number} margin
- * @param {Object} [opt]
- * @param {Array.<number>} [opt.hv=[1,1]] Only horizontal or only vertical.
- * @param {Array.<number>} [opt.boundingMode='all']
+ * @param el Should have `getBoundingRect` method.
+ * @param positionInfo
+ * @param positionInfo.left
+ * @param positionInfo.top
+ * @param positionInfo.right
+ * @param positionInfo.bottom
+ * @param positionInfo.width Only for opt.boundingModel: 'raw'
+ * @param positionInfo.height Only for opt.boundingModel: 'raw'
+ * @param containerRect
+ * @param margin
+ * @param opt
+ * @param opt.hv Only horizontal or only vertical. Default to be [1, 1]
+ * @param opt.boundingMode
  *        Specify how to calculate boundingRect when locating.
  *        'all': Position the boundingRect that is transformed and uioned
  *               both itself and its descendants.
@@ -323,9 +331,18 @@ export function getLayoutRect(
  *               container. (Consider a rotated circle needs to be located in a corner.)
  *               In this mode positionInfo.width/height can only be number.
  */
-export function positionElement(el, positionInfo, containerRect, margin, opt) {
-    var h = !opt || !opt.hv || opt.hv[0];
-    var v = !opt || !opt.hv || opt.hv[1];
+export function positionElement(
+    el:  Element,
+    positionInfo: BoxLayoutOptionMixin,
+    containerRect: RectLike,
+    margin: number[] | number,
+    opt: {
+        hv: [1 | 0, 1 | 0],
+        boundingMode: 'all' | 'raw'
+    }
+) {
+    const h = !opt || !opt.hv || opt.hv[0];
+    const v = !opt || !opt.hv || opt.hv[1];
     var boundingMode = opt && opt.boundingMode || 'all';
 
     if (!h && !v) {
@@ -350,7 +367,7 @@ export function positionElement(el, positionInfo, containerRect, margin, opt) {
     }
 
     // The real width and height can not be specified but calculated by the given el.
-    positionInfo = getLayoutRect(
+    const layoutRect = getLayoutRect(
         zrUtil.defaults(
             {width: rect.width, height: rect.height},
             positionInfo
@@ -363,24 +380,24 @@ export function positionElement(el, positionInfo, containerRect, margin, opt) {
     // (see zrender/core/Transformable#getLocalTransform),
     // we can just only modify el.position to get final result.
     var elPos = el.position;
-    var dx = h ? positionInfo.x - rect.x : 0;
-    var dy = v ? positionInfo.y - rect.y : 0;
+    var dx = h ? layoutRect.x - rect.x : 0;
+    var dy = v ? layoutRect.y - rect.y : 0;
 
     el.attr('position', boundingMode === 'raw' ? [dx, dy] : [elPos[0] + dx, elPos[1] + dy]);
 }
 
 /**
- * @param {Object} option Contains some of the properties in HV_NAMES.
- * @param {number} hvIdx 0: horizontal; 1: vertical.
+ * @param option Contains some of the properties in HV_NAMES.
+ * @param hvIdx 0: horizontal; 1: vertical.
  */
-export function sizeCalculable(option, hvIdx) {
+export function sizeCalculable(option: BoxLayoutOptionMixin, hvIdx: number): boolean {
     return option[HV_NAMES[hvIdx][0]] != null
         || (option[HV_NAMES[hvIdx][1]] != null && option[HV_NAMES[hvIdx][2]] != null);
 }
 
 /**
  * Consider Case:
- * When defulat option has {left: 0, width: 100}, and we set {right: 0}
+ * When default option has {left: 0, width: 100}, and we set {right: 0}
  * through setOption or media query, using normal zrUtil.merge will cause
  * {right: 0} does not take effect.
  *
@@ -397,13 +414,22 @@ export function sizeCalculable(option, hvIdx) {
  *     }
  * });
  *
- * @param {Object} targetOption
- * @param {Object} newOption
- * @param {Object|string} [opt]
+ * @param targetOption
+ * @param newOption
+ * @param opt
  * @param {boolean|Array.<boolean>} [opt.ignoreSize=false] Used for the components
  *  that width (or height) should not be calculated by left and right (or top and bottom).
  */
-export function mergeLayoutParam(targetOption, newOption, opt) {
+export function mergeLayoutParam<T extends BoxLayoutOptionMixin>(
+    targetOption: T,
+    newOption: T,
+    opt?: {
+        /**
+         * Used for the components that width (or height) should not be calculated by left and right (or top and bottom).
+         */
+        ignoreSize?: boolean | [boolean, boolean]
+    }
+) {
     !zrUtil.isObject(opt) && (opt = {});
 
     var ignoreSize = opt.ignoreSize;
@@ -415,17 +441,17 @@ export function mergeLayoutParam(targetOption, newOption, opt) {
     copy(HV_NAMES[0], targetOption, hResult);
     copy(HV_NAMES[1], targetOption, vResult);
 
-    function merge(names, hvIdx) {
-        var newParams = {};
+    function merge(names: typeof HV_NAMES[number], hvIdx: number) {
+        var newParams: BoxLayoutOptionMixin = {};
         var newValueCount = 0;
-        var merged = {};
+        var merged: BoxLayoutOptionMixin = {};
         var mergedValueCount = 0;
         var enoughParamNumber = 2;
 
-        each(names, function (name) {
+        each(names, function (name: BoxLayoutKeys) {
             merged[name] = targetOption[name];
         });
-        each(names, function (name) {
+        each(names, function (name: BoxLayoutKeys) {
             // Consider case: newOption.width is null, which is
             // set by user for removing width setting.
             hasProp(newOption, name) && (newParams[name] = merged[name] = newOption[name]);
@@ -433,7 +459,7 @@ export function mergeLayoutParam(targetOption, newOption, opt) {
             hasValue(merged, name) && mergedValueCount++;
         });
 
-        if (ignoreSize[hvIdx]) {
+        if ((ignoreSize as [boolean, boolean])[hvIdx]) {
             // Only one of left/right is premitted to exist.
             if (hasValue(newOption, names[1])) {
                 merged[names[2]] = null;
@@ -470,15 +496,15 @@ export function mergeLayoutParam(targetOption, newOption, opt) {
         }
     }
 
-    function hasProp(obj, name) {
+    function hasProp(obj: object, name: string): boolean {
         return obj.hasOwnProperty(name);
     }
 
-    function hasValue(obj, name) {
+    function hasValue(obj: Dictionary<any>, name: string): boolean {
         return obj[name] != null && obj[name] !== 'auto';
     }
 
-    function copy(names, target, source) {
+    function copy(names: readonly string[], target: Dictionary<any>, source: Dictionary<any>) {
         each(names, function (name) {
             target[name] = source[name];
         });
@@ -487,10 +513,8 @@ export function mergeLayoutParam(targetOption, newOption, opt) {
 
 /**
  * Retrieve 'left', 'right', 'top', 'bottom', 'width', 'height' from object.
- * @param {Object} source
- * @return {Object} Result contains those props.
  */
-export function getLayoutParams(source) {
+export function getLayoutParams(source: BoxLayoutOptionMixin): BoxLayoutOptionMixin {
     return copyLayoutParams({}, source);
 }
 
@@ -499,8 +523,8 @@ export function getLayoutParams(source) {
  * @param {Object} source
  * @return {Object} Result contains those props.
  */
-export function copyLayoutParams(target, source) {
-    source && target && each(LOCATION_PARAMS, function (name) {
+export function copyLayoutParams(target: BoxLayoutOptionMixin, source: BoxLayoutOptionMixin): BoxLayoutOptionMixin {
+    source && target && each(LOCATION_PARAMS, function (name: BoxLayoutKeys) {
         source.hasOwnProperty(name) && (target[name] = source[name]);
     });
     return target;
diff --git a/src/util/number.ts b/src/util/number.ts
index 3a16456..ca6ee67 100644
--- a/src/util/number.ts
+++ b/src/util/number.ts
@@ -17,8 +17,6 @@
 * under the License.
 */
 
-// @ts-nocheck
-
 /*
 * A third-party license is embeded for some of the code in this file:
 * The method "quantile" was copied from "d3.js".
@@ -32,20 +30,23 @@ import * as zrUtil from 'zrender/src/core/util';
 
 var RADIAN_EPSILON = 1e-4;
 
-function _trim(str) {
+function _trim(str: string): string {
     return str.replace(/^\s+|\s+$/g, '');
 }
 
 /**
  * Linear mapping a value from domain to range
- * @memberOf module:echarts/util/number
- * @param  {(number|Array.<number>)} val
- * @param  {Array.<number>} domain Domain extent domain[0] can be bigger than domain[1]
- * @param  {Array.<number>} range  Range extent range[0] can be bigger than range[1]
- * @param  {boolean} clamp
- * @return {(number|Array.<number>}
+ * @param  val
+ * @param  domain Domain extent domain[0] can be bigger than domain[1]
+ * @param  range  Range extent range[0] can be bigger than range[1]
+ * @param  clamp Default to be false
  */
-export function linearMap(val, domain, range, clamp) {
+export function linearMap(
+    val: number,
+    domain: [number, number],
+    range: [number, number],
+    clamp?: boolean
+): number {
     var subDomain = domain[1] - domain[0];
     var subRange = range[1] - range[0];
 
@@ -93,12 +94,8 @@ export function linearMap(val, domain, range, clamp) {
 /**
  * Convert a percent string to absolute number.
  * Returns NaN if percent is not a valid string or number
- * @memberOf module:echarts/util/number
- * @param {string|number} percent
- * @param {number} all
- * @return {number}
  */
-export function parsePercent(percent, all) {
+export function parsePercent(percent: number | string, all: number): number {
     switch (percent) {
         case 'center':
         case 'middle':
@@ -127,13 +124,8 @@ export function parsePercent(percent, all) {
 /**
  * (1) Fix rounding error of float numbers.
  * (2) Support return string to avoid scientific notation like '3.5e-7'.
- *
- * @param {number} x
- * @param {number} [precision]
- * @param {boolean} [returnStr]
- * @return {number|string}
  */
-export function round(x, precision, returnStr) {
+export function round(x: number | string, precision: number, returnStr?: boolean): string | number {
     if (precision == null) {
         precision = 10;
     }
@@ -144,13 +136,10 @@ export function round(x, precision, returnStr) {
 }
 
 /**
- * asc sort arr.
+ * Inplacd asc sort arr.
  * The input arr will be modified.
- *
- * @param {Array} arr
- * @return {Array} The input arr.
  */
-export function asc(arr) {
+export function asc(arr: number[]): number[] {
     arr.sort(function (a, b) {
         return a - b;
     });
@@ -159,9 +148,8 @@ export function asc(arr) {
 
 /**
  * Get precision
- * @param {number} val
  */
-export function getPrecision(val) {
+export function getPrecision(val: string | number): number {
     val = +val;
     if (isNaN(val)) {
         return 0;
@@ -180,10 +168,9 @@ export function getPrecision(val) {
 }
 
 /**
- * @param {string|number} val
- * @return {number}
+ * Get precision with slow but safe method
  */
-export function getPrecisionSafe(val) {
+export function getPrecisionSafe(val: string | number): number {
     var str = val.toString();
 
     // Consider scientific notation: '3.4e-12' '3.4e+12'
@@ -200,12 +187,8 @@ export function getPrecisionSafe(val) {
 
 /**
  * Minimal dicernible data precisioin according to a single pixel.
- *
- * @param {Array.<number>} dataExtent
- * @param {Array.<number>} pixelExtent
- * @return {number} precision
  */
-export function getPixelPrecision(dataExtent, pixelExtent) {
+export function getPixelPrecision(dataExtent: [number, number], pixelExtent: [number, number]): number {
     var log = Math.log;
     var LN10 = Math.LN10;
     var dataQuantity = Math.floor(log(dataExtent[1] - dataExtent[0]) / LN10);
@@ -221,12 +204,12 @@ export function getPixelPrecision(dataExtent, pixelExtent) {
  * The largest remainer method is used.
  * https://en.wikipedia.org/wiki/Largest_remainder_method
  *
- * @param {Array.<number>} valueList a list of all data
- * @param {number} idx index of the data to be processed in valueList
- * @param {number} precision integer number showing digits of precision
- * @return {number} percent ranging from 0 to 100
+ * @param valueList a list of all data
+ * @param idx index of the data to be processed in valueList
+ * @param precision integer number showing digits of precision
+ * @return percent ranging from 0 to 100
  */
-export function getPercentWithPrecision(valueList, idx, precision) {
+export function getPercentWithPrecision(valueList: number[], idx: number, precision: number): number {
     if (!valueList[idx]) {
         return 0;
     }
@@ -282,10 +265,8 @@ export var MAX_SAFE_INTEGER = 9007199254740991;
 
 /**
  * To 0 - 2 * PI, considering negative radian.
- * @param {number} radian
- * @return {number}
  */
-export function remRadian(radian) {
+export function remRadian(radian: number): number {
     var pi2 = Math.PI * 2;
     return (radian % pi2 + pi2) % pi2;
 }
@@ -294,7 +275,7 @@ export function remRadian(radian) {
  * @param {type} radian
  * @return {boolean}
  */
-export function isRadianAroundZero(val) {
+export function isRadianAroundZero(val: number): boolean {
     return val > -RADIAN_EPSILON && val < RADIAN_EPSILON;
 }
 
@@ -303,7 +284,7 @@ var TIME_REG = /^(?:(\d{4})(?:[-\/](\d{1,2})(?:[-\/](\d{1,2})(?:[T ](\d{1,2})(?:
 /* eslint-enable */
 
 /**
- * @param {string|Date|number} value These values can be accepted:
+ * @param value These values can be accepted:
  *   + An instance of Date, represent a time in its own time zone.
  *   + Or string in a subset of ISO 8601, only including:
  *     + only year, month, date: '2012-03', '2012-03-01', '2012-03-01 05', '2012-03-01 05:06',
@@ -315,9 +296,9 @@ var TIME_REG = /^(?:(\d{4})(?:[-\/](\d{1,2})(?:[-\/](\d{1,2})(?:[T ](\d{1,2})(?:
  *     '2012', '2012-3-1', '2012/3/1', '2012/03/01',
  *     '2009/6/12 2:00', '2009/6/12 2:05:08', '2009/6/12 2:05:08.123'
  *   + a timestamp, which represent a time in UTC.
- * @return {Date} date
+ * @return date
  */
-export function parseDate(value) {
+export function parseDate(value: number | string | Date): Date {
     if (value instanceof Date) {
         return value;
     }
@@ -358,7 +339,7 @@ export function parseDate(value) {
         else {
             var hour = +match[4] || 0;
             if (match[8].toUpperCase() !== 'Z') {
-                hour -= match[8].slice(0, 3);
+                hour -= +match[8].slice(0, 3);
             }
             return new Date(Date.UTC(
                 +match[1],
@@ -381,10 +362,10 @@ export function parseDate(value) {
 /**
  * Quantity of a number. e.g. 0.1, 1, 10, 100
  *
- * @param  {number} val
- * @return {number}
+ * @param val
+ * @return
  */
-export function quantity(val) {
+export function quantity(val: number): number {
     return Math.pow(10, quantityExponent(val));
 }
 
@@ -392,10 +373,10 @@ export function quantity(val) {
  * Exponent of the quantity of a number
  * e.g., 1234 equals to 1.234*10^3, so quantityExponent(1234) is 3
  *
- * @param  {number} val non-negative value
- * @return {number}
+ * @param val non-negative value
+ * @return
  */
-export function quantityExponent(val) {
+export function quantityExponent(val: number): number {
     if (val === 0) {
         return 0;
     }
@@ -419,11 +400,11 @@ export function quantityExponent(val) {
  *
  * See "Nice Numbers for Graph Labels" of Graphic Gems.
  *
- * @param  {number} val Non-negative value.
- * @param  {boolean} round
- * @return {number}
+ * @param  val Non-negative value.
+ * @param  round
+ * @return Niced number
  */
-export function nice(val, round) {
+export function nice(val: number, round?: boolean): number {
     var exponent = quantityExponent(val);
     var exp10 = Math.pow(10, exponent);
     var f = val / exp10; // 1 <= f < 10
@@ -473,9 +454,9 @@ export function nice(val, round) {
  * This code was copied from "d3.js"
  * <https://github.com/d3/d3/blob/9cc9a875e636a1dcf36cc1e07bdf77e1ad6e2c74/src/arrays/quantile.js>.
  * See the license statement at the head of this file.
- * @param {Array.<number>} ascArr
+ * @param ascArr
  */
-export function quantile(ascArr, p) {
+export function quantile(ascArr: number[], p: number): number {
     var H = (ascArr.length - 1) * p + 1;
     var h = Math.floor(H);
     var v = +ascArr[h - 1];
@@ -483,6 +464,10 @@ export function quantile(ascArr, p) {
     return e ? v + e * (ascArr[h] - v) : v;
 }
 
+type IntervalItem = {
+    interval: [number, number]
+    close: [number, number]
+}
 /**
  * Order intervals asc, and split them when overlap.
  * expect(numberUtil.reformIntervals([
@@ -501,11 +486,11 @@ export function quantile(ascArr, p) {
  *     {interval: [62, 150], close: [0, 1]},
  *     {interval: [150, Infinity], close: [0, 0]}
  * ]);
- * @param {Array.<Object>} list, where `close` mean open or close
+ * @param list, where `close` mean open or close
  *        of the interval, and Infinity can be used.
- * @return {Array.<Object>} The origin list, which has been reformed.
+ * @return The origin list, which has been reformed.
  */
-export function reformIntervals(list) {
+export function reformIntervals(list: IntervalItem[]): IntervalItem[] {
     list.sort(function (a, b) {
         return littleThan(a, b, 0) ? -1 : 1;
     });
@@ -535,7 +520,7 @@ export function reformIntervals(list) {
 
     return list;
 
-    function littleThan(a, b, lg) {
+    function littleThan(a: IntervalItem, b: IntervalItem, lg: number): boolean {
         return a.interval[lg] < b.interval[lg]
             || (
                 a.interval[lg] === b.interval[lg]
@@ -551,10 +536,7 @@ export function reformIntervals(list) {
  * parseFloat NaNs numeric-cast false positives (null|true|false|"")
  * ...but misinterprets leading-number strings, particularly hex literals ("0x...")
  * subtraction forces infinities to NaN
- *
- * @param {*} v
- * @return {boolean}
  */
-export function isNumeric(v) {
+export function isNumeric(v: any): v is number {
     return v - parseFloat(v) >= 0;
 }
diff --git a/src/util/quickSelect.ts b/src/util/quickSelect.ts
index cfaf0f4..fe8f2d5 100644
--- a/src/util/quickSelect.ts
+++ b/src/util/quickSelect.ts
@@ -17,25 +17,24 @@
 * under the License.
 */
 
-// @ts-nocheck
-
 /**
  * Quick select n-th element in an array.
  *
  * Note: it will change the elements placement in array.
  */
 
-function defaultCompareFunc(a, b) {
+type CompareFunc<T> = (a: T, b: T) => number;
+function defaultCompareFunc(a: any, b: any): any {
     return a - b;
 }
 
-function swapElement(arr, idx0, idx1) {
+function swapElement<T>(arr: T[], idx0: number, idx1: number) {
     var tmp = arr[idx0];
     arr[idx0] = arr[idx1];
     arr[idx1] = tmp;
 }
 
-function select(arr, left, right, nth, compareFunc) {
+function select<T>(arr: T[], left: number, right: number, nth: number, compareFunc: CompareFunc<T>): number {
     var pivotIdx = left;
     var pivotValue;
     while (right > left) {
@@ -67,12 +66,6 @@ function select(arr, left, right, nth, compareFunc) {
 }
 
 /**
- * @alias module:echarts/core/quickSelect
- * @param {Array} arr
- * @param {number} [left]
- * @param {number} [right]
- * @param {number} nth
- * @param {Function} [compareFunc]
  * @example
  *     var quickSelect = require('echarts/core/quickSelect');
  *     var arr = [5, 2, 1, 4, 3]
@@ -81,17 +74,23 @@ function select(arr, left, right, nth, compareFunc) {
  *
  * @return {number}
  */
-export default function (arr, left, right, nth, compareFunc) {
+function quickSelect<T>(arr: T[], nth: number, compareFunc: CompareFunc<T>): number
+function quickSelect<T>(arr: T[], nth: number, left: number, right: number, compareFunc: CompareFunc<T>): number
+function quickSelect<T>(
+    arr: T[], left: number, right: number | CompareFunc<T>, nth?: number, compareFunc?: CompareFunc<T>
+): number {
     if (arguments.length <= 3) {
         nth = left;
         if (arguments.length === 2) {
             compareFunc = defaultCompareFunc;
         }
         else {
-            compareFunc = right;
+            compareFunc = right as CompareFunc<T>;
         }
         left = 0;
         right = arr.length - 1;
     }
-    return select(arr, left, right, nth, compareFunc);
-}
\ No newline at end of file
+    return select(arr, left, right as number, nth, compareFunc);
+}
+
+export default quickSelect;
\ No newline at end of file
diff --git a/src/util/shape/sausage.ts b/src/util/shape/sausage.ts
index 7ef84f4..20bd651 100644
--- a/src/util/shape/sausage.ts
+++ b/src/util/shape/sausage.ts
@@ -19,14 +19,14 @@
 
 // @ts-nocheck
 
-import {extendShape} from '../graphic';
+import {Path} from '../graphic';
 
 /**
  * Sausage: similar to sector, but have half circle on both sides
  * @public
  */
 
-export default extendShape({
+export default Path.extend({
 
     type: 'sausage',
 
diff --git a/src/util/symbol.ts b/src/util/symbol.ts
index 371bb07..9a26e50 100644
--- a/src/util/symbol.ts
+++ b/src/util/symbol.ts
@@ -17,20 +17,26 @@
 * under the License.
 */
 
-// @ts-nocheck
-
 // Symbol factory
 
 import * as zrUtil from 'zrender/src/core/util';
 import * as graphic from './graphic';
 import BoundingRect from 'zrender/src/core/BoundingRect';
 import {calculateTextPosition} from 'zrender/src/contain/text';
+import { Dictionary } from 'zrender/src/core/types';
+
+type ECSymbol = graphic.Path & {
+    __isEmptyBrush?: boolean
+    setColor: (color: string, innerColor?: string) => void
+}
+type SymbolCtor = { new(): ECSymbol }
+type SymbolShapeMaker = (x: number, y: number, w: number, h: number, shape: Dictionary<any>) => void
 
 /**
  * Triangle shape
  * @inner
  */
-var Triangle = graphic.extendShape({
+const Triangle = graphic.Path.extend({
     type: 'triangle',
     shape: {
         cx: 0,
@@ -39,10 +45,10 @@ var Triangle = graphic.extendShape({
         height: 0
     },
     buildPath: function (path, shape) {
-        var cx = shape.cx;
-        var cy = shape.cy;
-        var width = shape.width / 2;
-        var height = shape.height / 2;
+        const cx = shape.cx;
+        const cy = shape.cy;
+        const width = shape.width / 2;
+        const height = shape.height / 2;
         path.moveTo(cx, cy - height);
         path.lineTo(cx + width, cy + height);
         path.lineTo(cx - width, cy + height);
@@ -54,7 +60,7 @@ var Triangle = graphic.extendShape({
  * Diamond shape
  * @inner
  */
-var Diamond = graphic.extendShape({
+const Diamond = graphic.Path.extend({
     type: 'diamond',
     shape: {
         cx: 0,
@@ -63,10 +69,10 @@ var Diamond = graphic.extendShape({
         height: 0
     },
     buildPath: function (path, shape) {
-        var cx = shape.cx;
-        var cy = shape.cy;
-        var width = shape.width / 2;
-        var height = shape.height / 2;
+        const cx = shape.cx;
+        const cy = shape.cy;
+        const width = shape.width / 2;
+        const height = shape.height / 2;
         path.moveTo(cx, cy - height);
         path.lineTo(cx + width, cy);
         path.lineTo(cx, cy + height);
@@ -79,7 +85,7 @@ var Diamond = graphic.extendShape({
  * Pin shape
  * @inner
  */
-var Pin = graphic.extendShape({
+const Pin = graphic.Path.extend({
     type: 'pin',
     shape: {
         // x, y on the cusp
@@ -90,25 +96,25 @@ var Pin = graphic.extendShape({
     },
 
     buildPath: function (path, shape) {
-        var x = shape.x;
-        var y = shape.y;
-        var w = shape.width / 5 * 3;
+        const x = shape.x;
+        const y = shape.y;
+        const w = shape.width / 5 * 3;
         // Height must be larger than width
-        var h = Math.max(w, shape.height);
-        var r = w / 2;
+        const h = Math.max(w, shape.height);
+        const r = w / 2;
 
         // Dist on y with tangent point and circle center
-        var dy = r * r / (h - r);
-        var cy = y - h + r + dy;
-        var angle = Math.asin(dy / r);
+        const dy = r * r / (h - r);
+        const cy = y - h + r + dy;
+        const angle = Math.asin(dy / r);
         // Dist on x with tangent point and circle center
-        var dx = Math.cos(angle) * r;
+        const dx = Math.cos(angle) * r;
 
-        var tanX = Math.sin(angle);
-        var tanY = Math.cos(angle);
+        const tanX = Math.sin(angle);
+        const tanY = Math.cos(angle);
 
-        var cpLen = r * 0.6;
-        var cpLen2 = r * 0.7;
+        const cpLen = r * 0.6;
+        const cpLen2 = r * 0.7;
 
         path.moveTo(x - dx, cy + dy);
 
@@ -135,7 +141,7 @@ var Pin = graphic.extendShape({
  * Arrow shape
  * @inner
  */
-var Arrow = graphic.extendShape({
+const Arrow = graphic.Path.extend({
 
     type: 'arrow',
 
@@ -147,11 +153,11 @@ var Arrow = graphic.extendShape({
     },
 
     buildPath: function (ctx, shape) {
-        var height = shape.height;
-        var width = shape.width;
-        var x = shape.x;
-        var y = shape.y;
-        var dx = width / 3 * 2;
+        const height = shape.height;
+        const width = shape.width;
+        const x = shape.x;
+        const y = shape.y;
+        const dx = width / 3 * 2;
         ctx.moveTo(x, y);
         ctx.lineTo(x + dx, y + height);
         ctx.lineTo(x, y + height / 4 * 3);
@@ -163,32 +169,33 @@ var Arrow = graphic.extendShape({
 
 /**
  * Map of path contructors
- * @type {Object.<string, module:zrender/graphic/Path>}
  */
-var symbolCtors = {
+const symbolCtors: Dictionary<SymbolCtor> = {
 
-    line: graphic.Line,
+    // TODO
+    line: graphic.Line as unknown as SymbolCtor,
 
-    rect: graphic.Rect,
+    rect: graphic.Rect as unknown as SymbolCtor,
 
-    roundRect: graphic.Rect,
+    roundRect: graphic.Rect as unknown as SymbolCtor,
 
-    square: graphic.Rect,
+    square: graphic.Rect as unknown as SymbolCtor,
 
-    circle: graphic.Circle,
+    circle: graphic.Circle as unknown as SymbolCtor,
 
-    diamond: Diamond,
+    diamond: Diamond as unknown as SymbolCtor,
 
-    pin: Pin,
+    pin: Pin as unknown as SymbolCtor,
 
-    arrow: Arrow,
+    arrow: Arrow as unknown as SymbolCtor,
 
-    triangle: Triangle
+    triangle: Triangle as unknown as SymbolCtor
 };
 
-var symbolShapeMakers = {
 
-    line: function (x, y, w, h, shape) {
+const symbolShapeMakers: Dictionary<SymbolShapeMaker> = {
+
+    line: function (x: number, y: number, w: number, h: number, shape: graphic.Line['shape']) {
         // FIXME
         shape.x1 = x;
         shape.y1 = y + h / 2;
@@ -196,14 +203,14 @@ var symbolShapeMakers = {
         shape.y2 = y + h / 2;
     },
 
-    rect: function (x, y, w, h, shape) {
+    rect: function (x: number, y: number, w: number, h: number, shape: graphic.Rect['shape']) {
         shape.x = x;
         shape.y = y;
         shape.width = w;
         shape.height = h;
     },
 
-    roundRect: function (x, y, w, h, shape) {
+    roundRect: function (x: number, y: number, w: number, h: number, shape: graphic.Rect['shape']) {
         shape.x = x;
         shape.y = y;
         shape.width = w;
@@ -211,7 +218,7 @@ var symbolShapeMakers = {
         shape.r = Math.min(w, h) / 4;
     },
 
-    square: function (x, y, w, h, shape) {
+    square: function (x: number, y: number, w: number, h: number, shape: graphic.Rect['shape']) {
         var size = Math.min(w, h);
         shape.x = x;
         shape.y = y;
@@ -219,35 +226,35 @@ var symbolShapeMakers = {
         shape.height = size;
     },
 
-    circle: function (x, y, w, h, shape) {
+    circle: function (x: number, y: number, w: number, h: number, shape: graphic.Circle['shape']) {
         // Put circle in the center of square
         shape.cx = x + w / 2;
         shape.cy = y + h / 2;
         shape.r = Math.min(w, h) / 2;
     },
 
-    diamond: function (x, y, w, h, shape) {
+    diamond: function (x: number, y: number, w: number, h: number, shape: InstanceType<typeof Diamond>['shape']) {
         shape.cx = x + w / 2;
         shape.cy = y + h / 2;
         shape.width = w;
         shape.height = h;
     },
 
-    pin: function (x, y, w, h, shape) {
+    pin: function (x: number, y: number, w: number, h: number, shape: InstanceType<typeof Pin>['shape']) {
         shape.x = x + w / 2;
         shape.y = y + h / 2;
         shape.width = w;
         shape.height = h;
     },
 
-    arrow: function (x, y, w, h, shape) {
+    arrow: function (x: number, y: number, w: number, h: number, shape: InstanceType<typeof Arrow>['shape']) {
         shape.x = x + w / 2;
         shape.y = y + h / 2;
         shape.width = w;
         shape.height = h;
     },
 
-    triangle: function (x, y, w, h, shape) {
+    triangle: function (x: number, y: number, w: number, h: number, shape: InstanceType<typeof Triangle>['shape']) {
         shape.cx = x + w / 2;
         shape.cy = y + h / 2;
         shape.width = w;
@@ -255,12 +262,12 @@ var symbolShapeMakers = {
     }
 };
 
-var symbolBuildProxies = {};
+var symbolBuildProxies: Dictionary<ECSymbol> = {};
 zrUtil.each(symbolCtors, function (Ctor, name) {
     symbolBuildProxies[name] = new Ctor();
 });
 
-var SymbolClz = graphic.extendShape({
+var SymbolClz = graphic.Path.extend({
 
     type: 'symbol',
 
@@ -299,7 +306,7 @@ var SymbolClz = graphic.extendShape({
 });
 
 // Provide setColor helper method to avoid determine if set the fill or stroke outside
-function symbolPathSetColor(color, innerColor) {
+function symbolPathSetColor(this: ECSymbol, color: string, innerColor?: string) {
     if (this.type !== 'image') {
         var symbolStyle = this.style;
         var symbolShape = this.shape;
@@ -330,14 +337,22 @@ function symbolPathSetColor(color, innerColor) {
  * @param {boolean} [keepAspect=false] whether to keep the ratio of w/h,
  *                            for path and image only.
  */
-export function createSymbol(symbolType, x, y, w, h, color, keepAspect) {
+export function createSymbol(
+    symbolType: string,
+    x: number,
+    y: number,
+    w: number,
+    h: number,
+    color?: string,
+    keepAspect?: boolean
+): graphic.Path | graphic.Image {
     // TODO Support image object, DynamicImage.
 
     var isEmpty = symbolType.indexOf('empty') === 0;
     if (isEmpty) {
         symbolType = symbolType.substr(5, 1).toLowerCase() + symbolType.substr(6);
     }
-    var symbolPath;
+    var symbolPath: ECSymbol | graphic.Image;
 
     if (symbolType.indexOf('image://') === 0) {
         symbolPath = graphic.makeImage(
@@ -352,7 +367,7 @@ export function createSymbol(symbolType, x, y, w, h, color, keepAspect) {
             {},
             new BoundingRect(x, y, w, h),
             keepAspect ? 'center' : 'cover'
-        );
+        ) as unknown as ECSymbol;
     }
     else {
         symbolPath = new SymbolClz({
@@ -363,14 +378,14 @@ export function createSymbol(symbolType, x, y, w, h, color, keepAspect) {
                 width: w,
                 height: h
             }
-        });
+        }) as unknown as ECSymbol;
     }
 
-    symbolPath.__isEmptyBrush = isEmpty;
+    (symbolPath as ECSymbol).__isEmptyBrush = isEmpty;
 
-    symbolPath.setColor = symbolPathSetColor;
+    (symbolPath as ECSymbol).setColor = symbolPathSetColor;
 
-    symbolPath.setColor(color);
+    (symbolPath as ECSymbol).setColor(color);
 
     return symbolPath;
 }
diff --git a/src/util/throttle.ts b/src/util/throttle.ts
index 48026eb..159d6ac 100755
--- a/src/util/throttle.ts
+++ b/src/util/throttle.ts
@@ -24,6 +24,7 @@ var ORIGIN_METHOD = '\0__throttleOriginMethod';
 var RATE = '\0__throttleRate';
 var THROTTLE_TYPE = '\0__throttleType';
 
+type ThrottleFunction = () => void;
 /**
  * @public
  * @param {(Function)} fn
@@ -33,7 +34,7 @@ var THROTTLE_TYPE = '\0__throttleType';
  *        false: If call interval less than `delay, call works on fixed rate.
  * @return {(Function)} throttled fn.
  */
-export function throttle(fn, delay?, debounce?) {
+export function throttle<T extends ThrottleFunction>(fn:T, delay?: number, debounce?: boolean): T {
 
     var currCall;
     var lastCall = 0;
@@ -127,14 +128,13 @@ export function throttle(fn, delay?, debounce?) {
  *     throttle.clear(this, '_dispatchAction');
  * };
  *
- * @public
- * @param {Object} obj
- * @param {string} fnAttr
- * @param {number} [rate]
- * @param {string} [throttleType='fixRate'] 'fixRate' or 'debounce'
- * @return {Function} throttled function.
  */
-export function createOrUpdate(obj, fnAttr, rate, throttleType) {
+export function createOrUpdate<T, S extends keyof T, P = T[S]>(
+    obj: T,
+    fnAttr: S,
+    rate: number,
+    throttleType: 'fixRate' | 'debounce'
+): P extends ThrottleFunction ? P : never {
     var fn = obj[fnAttr];
 
     if (!fn) {
@@ -163,12 +163,8 @@ export function createOrUpdate(obj, fnAttr, rate, throttleType) {
 
 /**
  * Clear throttle. Example see throttle.createOrUpdate.
- *
- * @public
- * @param {Object} obj
- * @param {string} fnAttr
  */
-export function clear(obj, fnAttr) {
+export function clear<T, S extends keyof T>(obj: T, fnAttr: S): void {
     var fn = obj[fnAttr];
     if (fn && fn[ORIGIN_METHOD]) {
         obj[fnAttr] = fn[ORIGIN_METHOD];
diff --git a/src/util/types.ts b/src/util/types.ts
index 6a90cae..6cec92a 100644
--- a/src/util/types.ts
+++ b/src/util/types.ts
@@ -447,13 +447,14 @@ export type MediaUnit = {
     option: ECUnitOption
 };
 
-export interface BoxLayoutOption {
-    width?: number;
-    height?: number;
-    top?: number;
-    right?: number;
-    bottom?: number;
-    left?: number;
+/******************* Mixins for Common Option Properties   ********************** */
+export interface BoxLayoutOptionMixin {
+    width?: number | string;
+    height?: number | string;
+    top?: number | string;
+    right?: number | string;
+    bottom?: number | string;
+    left?: number | string;
 }
 export type ComponentLayoutMode = {
     // Only support 'box' now.
@@ -555,4 +556,3 @@ export interface SeriesOption extends ComponentOption{
     emphasis?: Dictionary<any>;
     // FIXME:TS more
 }
-


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