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/19 03:41:42 UTC

[incubator-echarts] branch typescript updated: ts: add generic in SeriesModel, ComponentModel. fix eslint. improve types in graphic.ts

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 275e487  ts: add generic in SeriesModel, ComponentModel. fix eslint. improve types in graphic.ts
275e487 is described below

commit 275e487eaf2b5131500a9d745e452c67d5b9ba3e
Author: pissang <bm...@gmail.com>
AuthorDate: Wed Feb 19 11:41:19 2020 +0800

    ts: add generic in SeriesModel, ComponentModel. fix eslint. improve types in graphic.ts
---
 src/.eslintrc.yaml                      |  22 ++++--
 src/chart/helper/createRenderPlanner.ts |   2 +-
 src/chart/pie/PieSeries.ts              |  69 +++++++++++++++---
 src/chart/pie/PieView.ts                |   6 +-
 src/component/helper/selectableMixin.ts |  12 +++-
 src/model/Component.ts                  |  41 +++++++----
 src/model/Global.ts                     |  18 +++--
 src/model/Model.ts                      |  52 ++++++++------
 src/model/Series.ts                     |  26 ++++---
 src/model/mixin/colorPalette.ts         |   8 ++-
 src/model/mixin/dataFormat.ts           |   9 +--
 src/stream/Scheduler.ts                 |   4 +-
 src/util/ECEventProcessor.ts            |   2 +-
 src/util/animation.ts                   |   8 ++-
 src/util/component.ts                   |   2 +-
 src/util/format.ts                      |   2 +-
 src/util/graphic.ts                     | 123 ++++++++++++++++----------------
 src/util/layout.ts                      |  13 +---
 src/util/model.ts                       |  20 ++++--
 src/util/types.ts                       | 109 +++++++++++++++++++++-------
 src/view/Chart.ts                       |   2 +-
 src/view/Component.ts                   |   2 +-
 22 files changed, 357 insertions(+), 195 deletions(-)

diff --git a/src/.eslintrc.yaml b/src/.eslintrc.yaml
index 136f443..bf1fd2c 100644
--- a/src/.eslintrc.yaml
+++ b/src/.eslintrc.yaml
@@ -1,4 +1,10 @@
 parser: "@typescript-eslint/parser"
+parserOptions:
+    ecmaVersion: 6
+    sourceType: module
+    ecmaFeatures:
+        modules: true
+    project: "tsconfig.json"
 plugins: ["@typescript-eslint"]
 env:
     browser: true
@@ -72,11 +78,6 @@ rules:
     no-shadow-restricted-names: 2
     no-undef: 2
     no-undef-init: 2
-    no-unused-vars:
-        - 2
-        -
-            vars: "local"
-            args: "none"
     no-use-before-define: 0
     brace-style:
         - 2
@@ -176,7 +177,7 @@ rules:
             allowParens: true
     no-class-assign: 2
     no-const-assign: 2
-    no-dupe-class-members: 2
+    # no-dupe-class-members: 2
     no-this-before-super: 0
     no-var: 0
     no-duplicate-imports: 2
@@ -184,4 +185,11 @@ rules:
     unicode-bom: 2
     max-statements-per-line: 2
 
-    no-useless-constructor: 0
\ No newline at end of file
+    no-useless-constructor: 0
+
+
+    "@typescript-eslint/no-unused-vars":
+        - 2
+        -
+            vars: "local"
+            args: "none"
\ No newline at end of file
diff --git a/src/chart/helper/createRenderPlanner.ts b/src/chart/helper/createRenderPlanner.ts
index ed7bc87..c1c1b76 100644
--- a/src/chart/helper/createRenderPlanner.ts
+++ b/src/chart/helper/createRenderPlanner.ts
@@ -21,7 +21,7 @@
 
 import {makeInner} from '../../util/model';
 import SeriesModel from '../../model/Series';
-import { StageHandlerPlanReturn, StageHandlerPlan } from '../../util/types';
+import { StageHandlerPlanReturn } from '../../util/types';
 
 /**
  * @return {string} If large mode changed, return string 'reset';
diff --git a/src/chart/pie/PieSeries.ts b/src/chart/pie/PieSeries.ts
index a5db3fa..cd300c8 100644
--- a/src/chart/pie/PieSeries.ts
+++ b/src/chart/pie/PieSeries.ts
@@ -21,29 +21,76 @@ import createListSimply from '../helper/createListSimply';
 import * as zrUtil from 'zrender/src/core/util';
 import * as modelUtil from '../../util/model';
 import {getPercentWithPrecision} from '../../util/number';
-import {DataSelectableMixin, SelectableTarget} from '../../component/helper/selectableMixin';
+import {DataSelectableMixin, SelectableTarget, DataSelectableOptionMixin} from '../../component/helper/selectableMixin';
 import {retrieveRawAttr} from '../../data/helper/dataProvider';
 import {makeSeriesEncodeForNameBased} from '../../data/helper/sourceHelper';
 import LegendVisualProvider from '../../visual/LegendVisualProvider';
 import SeriesModel from '../../model/Series';
-import { SeriesOption, DataParamsUserOutput, ParsedDataValue } from '../../util/types';
+import {
+    SeriesOption,
+    DataParamsUserOutput,
+    CircleLayoutOptionMixin,
+    LabelLineOption,
+    ItemStyleOption,
+    LabelOption,
+    BoxLayoutOptionMixin
+} from '../../util/types';
 import List from '../../data/List';
 
-export interface PieOption extends SeriesOption {
-    // FIXME:TS need more. [k: string]: any should be removed finally.
-    [k: string]: any,
 
-    animationType: string
+interface PieLabelOption extends LabelOption {
+    alignTo?: 'none' | 'labelLine' | 'edge'
+    margin?: string | number
+    bleedMargin?: number
+    distanceToLabelLine?: number
 }
+export interface PieSeriesOption extends
+    SeriesOption,
+    DataSelectableOptionMixin,
+    CircleLayoutOptionMixin,
+    BoxLayoutOptionMixin {
 
-class PieSeries extends SeriesModel {
+    hoverAnimation?: boolean
+
+    roseType?: 'radius' | 'area'
+
+    itemStyle?: ItemStyleOption
+    label?: PieLabelOption
+    labelLine?: LabelLineOption
+
+    clockwise?: boolean
+    startAngle?: number
+    minAngle?: number
+    minShowLabelAngle?: number
+
+    selectedOffset?: number
+    hoverOffset?: number
+
+    avoidLabelOverlap?: boolean
+    percentPrecision?: number
+
+    stillShowZeroSum?: boolean
+
+    emphasis?: {
+        itemStyle?: ItemStyleOption
+
+        label?: PieLabelOption
+
+        labelLine?: LabelLineOption
+    }
+
+    animationType?: 'expansion' | 'scale'
+    animationTypeUpdate?: 'transition' | 'expansion'
+}
+
+class PieSeries extends SeriesModel<PieSeriesOption> {
 
     static type = 'series.pie';
 
     /**
      * @overwrite
      */
-    init(option: PieOption): void {
+    init(option: PieSeriesOption): void {
         super.init.apply(this, arguments as any);
 
         // Enable legend selection for each data item
@@ -113,7 +160,7 @@ class PieSeries extends SeriesModel {
         return params;
     }
 
-    private _defaultLabelLine(option: PieOption): void {
+    private _defaultLabelLine(option: PieSeriesOption): void {
         // Extend labelLine emphasis
         modelUtil.defaultEmphasis(option, 'labelLine', ['show']);
 
@@ -126,7 +173,7 @@ class PieSeries extends SeriesModel {
             && option.emphasis.label.show;
     }
 
-    static defaultOption: PieOption = {
+    static defaultOption: PieSeriesOption = {
         zlevel: 0,
         z: 2,
         legendHoverLink: true,
@@ -219,7 +266,7 @@ class PieSeries extends SeriesModel {
 
 }
 
-interface PieSeries extends DataSelectableMixin {}
+interface PieSeries extends DataSelectableMixin<PieSeriesOption> {}
 zrUtil.tsMixin(PieSeries, DataSelectableMixin);
 
 SeriesModel.registerClass(PieSeries);
diff --git a/src/chart/pie/PieView.ts b/src/chart/pie/PieView.ts
index 445b112..60ae5d7 100644
--- a/src/chart/pie/PieView.ts
+++ b/src/chart/pie/PieView.ts
@@ -1,3 +1,4 @@
+
 /*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
@@ -21,7 +22,6 @@
 import * as zrUtil from 'zrender/src/core/util';
 import * as graphic from '../../util/graphic';
 import ChartView from '../../view/Chart';
-import SeriesModel from '../../model/Series';
 import GlobalModel from '../../model/Global';
 import ExtensionAPI from '../../ExtensionAPI';
 import { Payload, DisplayState } from '../../util/types';
@@ -122,7 +122,7 @@ class PiePiece extends graphic.Group {
 
         var seriesModel = data.hostModel as PieSeries;
         var itemModel = data.getItemModel(idx);
-        var layout = data.getItemLayout(idx);
+        var layout = data.getItemLayout(idx) as graphic.Sector['shape'];
         var sectorShape = zrUtil.extend({
             label: ''
         }, layout);
@@ -293,7 +293,7 @@ class PiePiece extends graphic.Group {
             labelModel,
             labelHoverModel,
             {
-                labelFetcher: data.hostModel,
+                labelFetcher: data.hostModel as PieSeries,
                 labelDataIndex: idx,
                 defaultText: labelLayout.text,
                 autoColor: visualColor,
diff --git a/src/component/helper/selectableMixin.ts b/src/component/helper/selectableMixin.ts
index 9ca7a61..c45db1e 100644
--- a/src/component/helper/selectableMixin.ts
+++ b/src/component/helper/selectableMixin.ts
@@ -25,16 +25,22 @@
 
 import * as zrUtil from 'zrender/src/core/util';
 import Model from '../../model/Model';
+import { Dictionary } from 'zrender/src/core/types';
 
-export type SelectableTarget = {
+export interface SelectableTarget {
     name: string,
     value: any,
     selected: boolean
 };
 
-interface DataSelectableMixin extends Pick<Model, 'get'> {};
+export interface DataSelectableOptionMixin {
+    selected?: Dictionary<boolean>
+    selectedMode?: 'single' | 'multiple' | boolean
+}
+
+interface DataSelectableMixin<Opt extends DataSelectableOptionMixin> extends Pick<Model<Opt>, 'get'> {};
 
-class DataSelectableMixin {
+class DataSelectableMixin<Opt extends DataSelectableOptionMixin> {
 
     private _targetList: SelectableTarget[];
 
diff --git a/src/model/Component.ts b/src/model/Component.ts
index 2e38e1f..afd1e98 100644
--- a/src/model/Component.ts
+++ b/src/model/Component.ts
@@ -34,11 +34,18 @@ import * as layout from '../util/layout';
 import boxLayoutMixin from './mixin/boxLayout';
 import { CoordinateSystem } from '../coord/CoordinateSystem';
 import GlobalModel from './Global';
-import { ComponentOption, ComponentMainType, ComponentSubType, ComponentFullType } from '../util/types';
+import {
+    ComponentOption,
+    ComponentMainType,
+    ComponentSubType,
+    ComponentFullType,
+    ComponentLayoutMode,
+    BoxLayoutOptionMixin
+} from '../util/types';
 
 var inner = makeInner();
 
-class ComponentModel extends Model {
+class ComponentModel<Opt extends ComponentOption = ComponentOption> extends Model<Opt> {
 
     // [Caution]: for compat the previous "class extend"
     // publich and protected fields must be initialized on
@@ -115,7 +122,7 @@ class ComponentModel extends Model {
      * Support merge layout params.
      * Only support 'box' now (left/right/top/bottom/width/height).
      */
-    readonly layoutMode: string | {ignoreSize: boolean};
+    readonly layoutMode: ComponentLayoutMode;
 
     // Injectable properties:
     __viewId: string;
@@ -131,26 +138,26 @@ class ComponentModel extends Model {
     })();
 
 
-    constructor(option: ComponentOption, parentModel: Model, ecModel: GlobalModel) {
+    constructor(option: Opt, parentModel: Model, ecModel: GlobalModel) {
         super(option, parentModel, ecModel);
         this.uid = componentUtil.getUID('ec_cpt_model');
     }
 
-    init(option: ComponentOption, parentModel: Model, ecModel: GlobalModel): void {
+    init(option: Opt, parentModel: Model, ecModel: GlobalModel): void {
         this.mergeDefaultAndTheme(option, ecModel);
     }
 
-    mergeDefaultAndTheme(option: ComponentOption, ecModel: GlobalModel): void {
+    mergeDefaultAndTheme(option: Opt, ecModel: GlobalModel): void {
         var layoutMode = this.layoutMode;
         var inputPositionParams = layoutMode
-            ? layout.getLayoutParams(option) : {};
+            ? layout.getLayoutParams(option as BoxLayoutOptionMixin) : {};
 
         var themeModel = ecModel.getTheme();
         zrUtil.merge(option, themeModel.get(this.mainType));
         zrUtil.merge(option, this.getDefaultOption());
 
         if (layoutMode) {
-            layout.mergeLayoutParam(option, inputPositionParams, layoutMode);
+            layout.mergeLayoutParam(option as BoxLayoutOptionMixin, inputPositionParams, layoutMode);
         }
     }
 
@@ -159,7 +166,11 @@ class ComponentModel extends Model {
 
         var layoutMode = this.layoutMode;
         if (layoutMode) {
-            layout.mergeLayoutParam(this.option, option, layoutMode);
+            layout.mergeLayoutParam(
+                this.option as BoxLayoutOptionMixin,
+                option as BoxLayoutOptionMixin,
+                layoutMode
+            );
         }
     }
 
@@ -252,10 +263,12 @@ class ComponentModel extends Model {
     }
 
     getReferringComponents(mainType: ComponentMainType): ComponentModel[] {
+        const indexKey = (mainType + 'Index') as keyof Opt;
+        const idKey = (mainType + 'Id') as keyof Opt;
         return this.ecModel.queryComponents({
             mainType: mainType,
-            index: this.get(mainType + 'Index', true),
-            id: this.get(mainType + 'Id', true)
+            index: this.get(indexKey, true) as unknown as number,
+            id: this.get(idKey, true) as unknown as string
         });
     }
 
@@ -278,14 +291,14 @@ class ComponentModel extends Model {
 //     }
 // );
 
-type ComponentModelConstructor = typeof ComponentModel
+export type ComponentModelConstructor = typeof ComponentModel
     & ClassManager
     & componentUtil.SubTypeDefaulterManager
     & ExtendableConstructor
     & componentUtil.TopologicalTravelable<object>;
 
 mountExtend(ComponentModel, Model);
-enableClassManagement(ComponentModel as ComponentModelConstructor, {registerWhenExtend: true})
+enableClassManagement(ComponentModel as ComponentModelConstructor, {registerWhenExtend: true});
 componentUtil.enableSubTypeDefaulter(ComponentModel as ComponentModelConstructor);
 componentUtil.enableTopologicalTravel(ComponentModel as ComponentModelConstructor, getDependencies);
 
@@ -311,6 +324,4 @@ function getDependencies(componentType: string): string[] {
 
 zrUtil.mixin(ComponentModel, boxLayoutMixin);
 
-export {ComponentModelConstructor};
-
 export default ComponentModel;
diff --git a/src/model/Global.ts b/src/model/Global.ts
index b4d3a05..c127fa9 100644
--- a/src/model/Global.ts
+++ b/src/model/Global.ts
@@ -43,7 +43,17 @@ import globalDefault from './globalDefault';
 import {ColorPaletteMixin} from './mixin/colorPalette';
 import {resetSourceDefaulter} from '../data/helper/sourceHelper';
 import SeriesModel from './Series';
-import { Payload, OptionPreprocessor, ECOption, ECUnitOption, ThemeOption, ComponentOption, ComponentMainType, ComponentSubType } from '../util/types';
+import {
+    Payload,
+    OptionPreprocessor,
+    ECOption,
+    ECUnitOption,
+    ThemeOption,
+    ComponentOption,
+    ComponentMainType,
+    ComponentSubType,
+    ColorPaletteOptionMixin
+} from '../util/types';
 import OptionManager from './OptionManager';
 import Scheduler from '../stream/Scheduler';
 import { Dictionary } from 'zrender/src/core/types';
@@ -613,7 +623,7 @@ class GlobalModel extends Model {
                     return series.componentIndex;
                 }) || []
             );
-        }
+        };
 
         assertSeriesInitialized = function (ecModel: GlobalModel): void {
             // Components that use _seriesIndices should depends on series component,
@@ -623,7 +633,7 @@ class GlobalModel extends Model {
                     throw new Error('Option should contains series.');
                 }
             }
-        }
+        };
 
         initBase = function (ecModel: GlobalModel, baseOption: ECUnitOption): void {
             baseOption = baseOption;
@@ -784,7 +794,7 @@ function filterBySubType(
         : components;
 }
 
-
+// @ts-ignore FIXME:GlobalOption
 interface GlobalModel extends ColorPaletteMixin {}
 tsMixin(GlobalModel, ColorPaletteMixin);
 
diff --git a/src/model/Model.ts b/src/model/Model.ts
index f65cebc..b3f73af 100644
--- a/src/model/Model.ts
+++ b/src/model/Model.ts
@@ -36,7 +36,7 @@ import textStyleMixin from './mixin/textStyle';
 import {LineStyleMixin} from './mixin/lineStyle';
 import {ItemStyleMixin} from './mixin/itemStyle';
 import GlobalModel from './Global';
-import { ModelOption } from '../util/types';
+import { ModelOption, ECUnitOption } from '../util/types';
 import { Dictionary } from 'zrender/src/core/types';
 
 var mixin = zrUtil.mixin;
@@ -44,9 +44,9 @@ var inner = makeInner();
 
 // Since model.option can be not only `Dictionary` but also primary types,
 // we do this conditional type to avoid getting type 'never';
-type Key<Opt> = Opt extends Dictionary<any>
+type Key<Opt> = Opt extends ECUnitOption
     ? keyof Opt : string;
-type Value<Opt, R> = Opt extends Dictionary<any>
+type Value<Opt, R> = Opt extends ECUnitOption
     ? (R extends keyof Opt ? Opt[R] : ModelOption)
     : ModelOption;
 
@@ -108,17 +108,21 @@ class Model<Opt extends ModelOption = ModelOption> {
     // FIXME:TS consider there is parentModel,
     // return type have to be ModelOption or can be Option<R>?
     // (Is there any chance that parentModel value type is different?)
-    get<R extends Key<Opt>>(
+    get<R extends keyof Opt>(
+        path: R, ignoreParent?: boolean
+    ): Opt[R];
+    get<R extends keyof Opt>(
         path: [R], ignoreParent?: boolean
-    ): Value<Opt, R>;
-    get<R extends Key<Opt>, S extends Key<Value<Opt, R>>>(
+    ): Opt[R];
+    get<R extends keyof Opt, S extends keyof Opt[R]>(
         path: [R, S], ignoreParent?: boolean
-    ): Value<Value<Opt, R>, S>;
-    get<R extends Key<Opt>, S extends Key<Value<Opt, R>>, T extends Key<Value<Value<Opt, R>, S>>>(
+    ): Opt[R][S];
+    get<R extends keyof Opt, S extends keyof Opt[R], T extends keyof Opt[R][S]>(
         path: [R, S, T], ignoreParent?: boolean
-    ): Value<Value<Value<Opt, R>, S>, T>;
+    ): Opt[R][S][T];
     // `path` can be 'xxx.yyy.zzz', so the return value type have to be `ModelOption`
-    get(path: string | string[], ignoreParent?: boolean): ModelOption;
+    // TODO: Type strict key check?
+    // get(path: string | string[], ignoreParent?: boolean): ModelOption;
     get(path: string | string[], ignoreParent?: boolean): ModelOption {
         if (path == null) {
             return this.option;
@@ -131,9 +135,9 @@ class Model<Opt extends ModelOption = ModelOption> {
         );
     }
 
-    getShallow<R extends Key<Opt>>(
+    getShallow<R extends keyof Opt>(
         key: R, ignoreParent?: boolean
-    ): Value<Opt, R> {
+    ): Opt[R] {
         var option = this.option;
 
         var val = option == null ? option : option[key];
@@ -145,17 +149,20 @@ class Model<Opt extends ModelOption = ModelOption> {
         return val;
     }
 
-    getModel<R extends Key<Opt>>(
+    getModel<R extends keyof Opt>(
+        path: R, parentModel?: Model
+    ): Model<Opt[R]>;
+    getModel<R extends keyof Opt>(
         path: [R], parentModel?: Model
-    ): Model<Value<Opt, R>>;
-    getModel<R extends Key<Opt>, S extends Key<Value<Opt, R>>>(
+    ): Model<Opt[R]>;
+    getModel<R extends keyof Opt, S extends keyof Opt[R]>(
         path: [R, S], parentModel?: Model
-    ): Model<Value<Value<Opt, R>, S>>;
-    getModel<R extends Key<Opt>, S extends Key<Value<Opt, R>>, T extends Key<Value<Value<Opt, R>, S>>>(
+    ): Model<Opt[R][S]>;
+    getModel<R extends keyof Opt, S extends keyof Opt[R], T extends keyof Opt[R][S]>(
         path: [R, S, T], parentModel?: Model
-    ): Model<Value<Value<Value<Opt, R>, S>, T>>;
+    ): Model<Opt[R][S][T]>;
     // `path` can be 'xxx.yyy.zzz', so the return value type have to be `Model<ModelOption>`
-    getModel(path: string | string[], parentModel?: Model): Model;
+    // getModel(path: string | string[], parentModel?: Model): Model;
     getModel(path: string | string[], parentModel?: Model): Model<any> {
         var obj = path == null
             ? this.option
@@ -164,7 +171,7 @@ class Model<Opt extends ModelOption = ModelOption> {
         var thisParentModel;
         parentModel = parentModel || (
             (thisParentModel = getParent(this, path))
-                && thisParentModel.getModel(path)
+                && thisParentModel.getModel(path as string)
         );
 
         return new Model(obj, parentModel, this.ecModel);
@@ -222,7 +229,7 @@ class Model<Opt extends ModelOption = ModelOption> {
 
 };
 
-function doGet(obj: ModelOption, pathArr: string[], parentModel?: Model) {
+function doGet(obj: ModelOption, pathArr: string[], parentModel?: Model<Dictionary<any>>) {
     for (var i = 0; i < pathArr.length; i++) {
         // Ignore empty
         if (!pathArr[i]) {
@@ -235,7 +242,8 @@ function doGet(obj: ModelOption, pathArr: string[], parentModel?: Model) {
         }
     }
     if (obj == null && parentModel) {
-        obj = parentModel.get(pathArr);
+        // TODO At most 3 items array.
+        obj = parentModel.get(pathArr as [string, string, string]);
     }
     return obj;
 }
diff --git a/src/model/Series.ts b/src/model/Series.ts
index 4191a1a..608aa14 100644
--- a/src/model/Series.ts
+++ b/src/model/Series.ts
@@ -29,7 +29,7 @@ import {
 import * as modelUtil from '../util/model';
 import {
     DataHost, DimensionName, StageHandlerProgressParams,
-    SeriesOption, ComponentLayoutMode, TooltipRenderMode, AxisValue, ZRColor
+    SeriesOption, ComponentLayoutMode, TooltipRenderMode, AxisValue, ZRColor, BoxLayoutOptionMixin
 } from '../util/types';
 import ComponentModel, { ComponentModelConstructor } from './Component';
 import {ColorPaletteMixin} from './mixin/colorPalette';
@@ -47,7 +47,7 @@ import {
 import {retrieveRawValue} from '../data/helper/dataProvider';
 import GlobalModel from './Global';
 import { CoordinateSystem } from '../coord/CoordinateSystem';
-import { ExtendableConstructor, mountExtend, ClassManager, Constructor } from '../util/clazz';
+import { ExtendableConstructor, mountExtend, Constructor } from '../util/clazz';
 import { PipelineContext, SeriesTaskContext, GeneralTask, OverallTask, SeriesTask } from '../stream/Scheduler';
 import LegendVisualProvider from '../visual/LegendVisualProvider';
 import List from '../data/List';
@@ -55,7 +55,7 @@ import Source from '../data/Source';
 
 var inner = modelUtil.makeInner();
 
-class SeriesModel extends ComponentModel {
+class SeriesModel<Opt extends SeriesOption = SeriesOption> extends ComponentModel<Opt> {
 
     // [Caution]: for compat the previous "class extend"
     // publich and protected fields must be initialized on
@@ -90,7 +90,7 @@ class SeriesModel extends ComponentModel {
     visualBorderColorAccessPath: string;
 
     // Support merge layout params.
-    readonly layoutMode: ComponentLayoutMode['type'] | ComponentLayoutMode;
+    readonly layoutMode: ComponentLayoutMode;
 
     readonly preventUsingHoverLayer: boolean;
 
@@ -148,7 +148,7 @@ class SeriesModel extends ComponentModel {
     mergeDefaultAndTheme(option: SeriesOption, ecModel: GlobalModel): void {
         var layoutMode = this.layoutMode;
         var inputPositionParams = layoutMode
-            ? getLayoutParams(option) : {};
+            ? getLayoutParams(option as BoxLayoutOptionMixin) : {};
 
         // Backward compat: using subType on theme.
         // But if name duplicate between series subType
@@ -167,10 +167,10 @@ class SeriesModel extends ComponentModel {
         // Default label emphasis `show`
         modelUtil.defaultEmphasis(option, 'label', ['show']);
 
-        this.fillDataTextStyle(option.data);
+        this.fillDataTextStyle(option.data as ArrayLike<any>);
 
         if (layoutMode) {
-            mergeLayoutParam(option, inputPositionParams, layoutMode);
+            mergeLayoutParam(option as BoxLayoutOptionMixin, inputPositionParams, layoutMode);
         }
     }
 
@@ -178,11 +178,15 @@ class SeriesModel extends ComponentModel {
         // this.settingTask.dirty();
 
         newSeriesOption = zrUtil.merge(this.option, newSeriesOption, true);
-        this.fillDataTextStyle(newSeriesOption.data);
+        this.fillDataTextStyle(newSeriesOption.data as ArrayLike<any>);
 
         var layoutMode = this.layoutMode;
         if (layoutMode) {
-            mergeLayoutParam(this.option, newSeriesOption, layoutMode);
+            mergeLayoutParam(
+                this.option as BoxLayoutOptionMixin,
+                newSeriesOption as BoxLayoutOptionMixin,
+                layoutMode
+            );
         }
 
         prepareSource(this);
@@ -465,7 +469,6 @@ class SeriesModel extends ComponentModel {
         if (env.node) {
             return false;
         }
-
         var animationEnabled = this.getShallow('animation');
         if (animationEnabled) {
             if (this.getData().count() > this.getShallow('animationThreshold')) {
@@ -548,7 +551,8 @@ class SeriesModel extends ComponentModel {
     }
 }
 
-interface SeriesModel extends DataFormatMixin, ColorPaletteMixin, DataHost {}
+interface SeriesModel<Opt extends SeriesOption = SeriesOption>
+    extends DataFormatMixin, ColorPaletteMixin<Opt>, DataHost {}
 zrUtil.tsMixin(SeriesModel, DataFormatMixin);
 zrUtil.tsMixin(SeriesModel, ColorPaletteMixin);
 
diff --git a/src/model/mixin/colorPalette.ts b/src/model/mixin/colorPalette.ts
index 3e72159..526a9c1 100644
--- a/src/model/mixin/colorPalette.ts
+++ b/src/model/mixin/colorPalette.ts
@@ -19,7 +19,7 @@
 
 import {makeInner, normalizeToArray} from '../../util/model';
 import Model from '../Model';
-import { ZRColor } from '../../util/types';
+import { ZRColor, ColorPaletteOptionMixin } from '../../util/types';
 
 var inner = makeInner();
 
@@ -36,9 +36,11 @@ function getNearestColorPalette(
     return colors[paletteNum - 1];
 }
 
-interface ColorPaletteMixin extends Pick<Model, 'get'> {}
 
-class ColorPaletteMixin {
+interface ColorPaletteMixin<T extends ColorPaletteOptionMixin = ColorPaletteOptionMixin>
+    extends Pick<Model<T>, 'get'> {}
+
+class ColorPaletteMixin<T extends ColorPaletteOptionMixin = ColorPaletteOptionMixin> {
 
     clearColorPalette(this: ColorPaletteMixin) {
         inner(this).colorIdx = 0;
diff --git a/src/model/mixin/dataFormat.ts b/src/model/mixin/dataFormat.ts
index 3c3b283..e230fbe 100644
--- a/src/model/mixin/dataFormat.ts
+++ b/src/model/mixin/dataFormat.ts
@@ -18,7 +18,7 @@
 */
 
 import {retrieveRawValue} from '../../data/helper/dataProvider';
-import {getTooltipMarker, formatTpl, TooltipMarker} from '../../util/format';
+import {getTooltipMarker, formatTpl} from '../../util/format';
 import { getTooltipRenderMode } from '../../util/model';
 import { DataHost, DisplayState, TooltipRenderMode, DataParamsUserOutput } from '../../util/types';
 import GlobalModel from '../Global';
@@ -56,6 +56,7 @@ class DataFormatMixin {
         var color = data.getItemVisual(dataIndex, 'color');
         var borderColor = data.getItemVisual(dataIndex, 'borderColor');
         var tooltipModel = this.ecModel.getComponent('tooltip');
+        // @ts-ignore FIXME:TooltipModel
         var renderModeOption = tooltipModel && tooltipModel.get('renderMode');
         var renderMode = getTooltipRenderMode(renderModeOption);
         var mainType = this.mainType;
@@ -116,9 +117,9 @@ class DataFormatMixin {
             params.value = params.value[dimIndex];
         }
 
-        var formatter = itemModel.get(
-            status === 'normal'
-            ? [labelProp || 'label', 'formatter']
+        // @ts-ignore FIXME:TooltipModel
+        var formatter = itemModel.get(status === 'normal'
+            ? [(labelProp || 'label'), 'formatter']
             : [status, labelProp || 'label', 'formatter']
         );
 
diff --git a/src/stream/Scheduler.ts b/src/stream/Scheduler.ts
index 8956bd0..49b44fd 100644
--- a/src/stream/Scheduler.ts
+++ b/src/stream/Scheduler.ts
@@ -28,7 +28,7 @@ import ExtensionAPI from '../ExtensionAPI';
 import {normalizeToArray} from '../util/model';
 import {
     StageHandler, StageHandlerOverallReset, VisualType, StageHandlerInput,
-    Payload, StageHandlerReset, StageHandlerPlan, StageHandlerProgressExecutor
+    Payload, StageHandlerReset, StageHandlerPlan, StageHandlerProgressExecutor, LarginOptionMixin, SeriesOption
 } from '../util/types';
 import { EChartsType } from '../echarts';
 import SeriesModel from '../model/Series';
@@ -204,7 +204,7 @@ class Scheduler {
      * Caution:
      * `updateStreamModes` use `seriesModel.getData()`.
      */
-    updateStreamModes(seriesModel: SeriesModel, view: ChartView): void {
+    updateStreamModes(seriesModel: SeriesModel<SeriesOption & LarginOptionMixin>, view: ChartView): void {
         var pipeline = this._pipelineMap.get(seriesModel.uid);
         var data = seriesModel.getData();
         var dataLen = data.count();
diff --git a/src/util/ECEventProcessor.ts b/src/util/ECEventProcessor.ts
index d113edb..e4d4ecd 100644
--- a/src/util/ECEventProcessor.ts
+++ b/src/util/ECEventProcessor.ts
@@ -22,7 +22,7 @@
 import { EventProcessor, EventQuery } from 'zrender/src/core/Eventful';
 import { ECEvent, NormalizedEventQuery, EventQueryItem } from './types';
 import ComponentModel from '../model/Component';
-import ComponentView from '../view/Component'
+import ComponentView from '../view/Component';
 import ChartView from '../view/Chart';
 import * as zrUtil from 'zrender/src/core/util';
 import { parseClassType } from './clazz';
diff --git a/src/util/animation.ts b/src/util/animation.ts
index 08275c8..f5dad67 100644
--- a/src/util/animation.ts
+++ b/src/util/animation.ts
@@ -64,7 +64,13 @@ export function createWrap() {
          *     add(el, target, time);
          *     add(el, target);
          */
-        add: function (el: Element, target: ElementProps, time?: number, delay?: number | easingType, easing?: easingType) {
+        add: function (
+            el: Element,
+            target: ElementProps,
+            time?: number,
+            delay?: number | easingType,
+            easing?: easingType
+        ) {
             if (zrUtil.isString(delay)) {
                 easing = delay;
                 delay = 0;
diff --git a/src/util/component.ts b/src/util/component.ts
index 2d84c38..c1b3855 100644
--- a/src/util/component.ts
+++ b/src/util/component.ts
@@ -113,7 +113,7 @@ export function enableTopologicalTravel<T>(
      * @param callback Params: componentType, dependencies.
      * @param context Scope of callback.
      */
-    entity.topologicalTravel = function <Ctx>(
+    entity.topologicalTravel = function<Ctx> (
         targetNameList: ComponentMainType[],
         fullNameList: ComponentMainType[],
         callback: (this: Ctx, mainType: ComponentMainType, dependencies: ComponentMainType[]) => void,
diff --git a/src/util/format.ts b/src/util/format.ts
index c669d12..54b630c 100644
--- a/src/util/format.ts
+++ b/src/util/format.ts
@@ -22,7 +22,7 @@ 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 { StyleProps } from 'zrender/src/graphic/Style';
 // import Text from 'zrender/src/graphic/Text';
 
 /**
diff --git a/src/util/graphic.ts b/src/util/graphic.ts
index 5f108de..63174dc 100644
--- a/src/util/graphic.ts
+++ b/src/util/graphic.ts
@@ -42,13 +42,13 @@ import RadialGradient from 'zrender/src/graphic/RadialGradient';
 import BoundingRect, { RectLike } from 'zrender/src/core/BoundingRect';
 import IncrementalDisplayable from 'zrender/src/graphic/IncrementalDisplayable';
 import * as subPixelOptimizeUtil from 'zrender/src/graphic/helper/subPixelOptimize';
-import { Dictionary, ImageLike, PropType } from 'zrender/src/core/types';
+import { Dictionary, ImageLike } from 'zrender/src/core/types';
 import LRU from 'zrender/src/core/LRU';
 import Displayable, { DisplayableProps } from 'zrender/src/graphic/Displayable';
-import Style, { StyleProps } from 'zrender/src/graphic/Style';
+import { StyleProps } from 'zrender/src/graphic/Style';
 import { PatternObject } from 'zrender/src/graphic/Pattern';
 import { GradientObject } from 'zrender/src/graphic/Gradient';
-import Element, { ElementEvent, ElementProps } from 'zrender/src/Element';
+import Element, { ElementEvent } from 'zrender/src/Element';
 import Model from '../model/Model';
 import { AnimationOptionMixin, LabelOption, AnimationDelayCallbackParam } from './types';
 import GlobalModel from '../model/Global';
@@ -84,7 +84,7 @@ type ExtendShapeOpt = Parameters<typeof Path.extend>[0];
 type ExtendShapeReturn = ReturnType<typeof Path.extend>;
 
 
-type ExtendedDisplayable = Displayable & {
+type ExtendedProps = {
     __hoverStlDirty?: boolean
     __hoverStl?: StyleProps
     __cachedNormalStl?: StyleProps
@@ -97,7 +97,10 @@ type ExtendedDisplayable = Displayable & {
     __highDownOnUpdate: (fromState: AvailableStates, toState: AvailableStates) => void
 
     __highDownDispatcher: boolean
+
 }
+type ExtendedElement = Element & ExtendedProps
+type ExtendedDisplayable = Displayable & ExtendedProps
 
 type ExtendedStyleProps = StyleProps & {
     insideRollback?: StyleProps
@@ -131,11 +134,6 @@ type TextCommonParams = {
     textStyle?: StyleProps
 }
 
-// Method for type guard
-function isExtendedDisplayable(el: Displayable): el is ExtendedDisplayable {
-    return true;
-}
-
 /**
  * Extend shape with parameters
  */
@@ -399,7 +397,7 @@ function cacheElementStl(el: ExtendedDisplayable) {
     normalStyle.stroke = elStyle.stroke;
 }
 
-function singleEnterEmphasis(el:  ExtendedDisplayable) {
+function singleEnterEmphasis(el: ExtendedDisplayable) {
     var hoverStl = el.__hoverStl;
 
     if (!hoverStl || el.__highlighted) {
@@ -511,8 +509,8 @@ function singleEnterNormal(el: ExtendedDisplayable) {
 }
 
 function traverseUpdate<T>(
-    el: ExtendedDisplayable,
-    updater: (this: void, el: Displayable, commonParam?: T) => void,
+    el: ExtendedElement,
+    updater: (this: void, el: Element, commonParam?: T) => void,
     commonParam?: T
 ) {
     // If root is group, also enter updater for `highDownOnUpdate`.
@@ -547,11 +545,12 @@ function traverseUpdate<T>(
  *        as `false` to disable the hover style.
  *        Otherwise, use the default hover style if not provided.
  */
-export function setElementHoverStyle(el: ExtendedDisplayable, hoverStl: StyleProps) {
+export function setElementHoverStyle(el: Displayable, hoverStl: StyleProps) {
+    const extendedEl = el as ExtendedDisplayable;
     // For performance consideration, it might be better to make the "hover style" only the
     // difference properties from the "normal style", but not a entire copy of all styles.
-    hoverStl = el.__hoverStl = hoverStl !== false && (el.hoverStyle || hoverStl || {});
-    el.__hoverStlDirty = true;``
+    hoverStl = extendedEl.__hoverStl = hoverStl !== false && (extendedEl.hoverStyle || hoverStl || {});
+    extendedEl.__hoverStlDirty = true;
 
     // FIXME
     // It is not completely right to save "normal"/"emphasis" flag on elements.
@@ -559,19 +558,19 @@ export function setElementHoverStyle(el: ExtendedDisplayable, hoverStl: StylePro
     // (1) A highlighted elements are moved out of the view port and re-enter
     // again by dataZoom.
     // (2) call `setOption` and replace elements totally when they are highlighted.
-    if (el.__highlighted) {
+    if (extendedEl.__highlighted) {
         // Consider the case:
         // The styles of a highlighted `el` is being updated. The new "emphasis style"
         // should be adapted to the `el`. Notice here new "normal styles" should have
         // been set outside and the cached "normal style" is out of date.
-        el.__cachedNormalStl = null;
+        extendedEl.__cachedNormalStl = null;
         // Do not clear `__cachedNormalZ2` here, because setting `z2` is not a constraint
         // of this method. In most cases, `z2` is not set and hover style should be able
         // to rollback. Of course, that would bring bug, but only in a rare case, see
         // `doSingleLeaveHover` for details.
-        singleEnterNormal(el);
+        singleEnterNormal(extendedEl);
 
-        singleEnterEmphasis(el);
+        singleEnterEmphasis(extendedEl);
     }
 }
 
@@ -634,9 +633,9 @@ function shouldSilent(el: ExtendedDisplayable, e: ElementEvent) {
  *
  * (3) These input parameters can be set directly on `el`:
  */
-export function setHoverStyle(el: Displayable, hoverStyle?: StyleProps) {
+export function setHoverStyle(el: Element, hoverStyle?: StyleProps) {
     setAsHighDownDispatcher(el, true);
-    traverseUpdate(el as ExtendedDisplayable, setElementHoverStyle, hoverStyle);
+    traverseUpdate(el as ExtendedElement, setElementHoverStyle, hoverStyle);
 }
 
 /**
@@ -673,32 +672,31 @@ export function setHoverStyle(el: Displayable, hoverStyle?: StyleProps) {
  *        hover-highlight on touch device.
  * @param {boolean} [asDispatcher=true] If `false`, do not set as "highDownDispatcher".
  */
-export function setAsHighDownDispatcher(el: Displayable, asDispatcher: boolean) {
-    var disable = asDispatcher === false;
-    if (isExtendedDisplayable(el)) {
-        // Make `highDownSilentOnTouch` and `highDownOnUpdate` only work after
-        // `setAsHighDownDispatcher` called. Avoid it is modified by user unexpectedly.
-        el.__highDownSilentOnTouch = el.highDownSilentOnTouch;
-        el.__highDownOnUpdate = el.highDownOnUpdate;
-
-        // Simple optimize, since this method might be
-        // called for each elements of a group in some cases.
-        if (!disable || el.__highDownDispatcher) {
-            var method: 'on' | 'off' = disable ? 'off' : 'on';
-
-            // Duplicated function will be auto-ignored, see Eventful.js.
-            el[method]('mouseover', onElementMouseOver)[method]('mouseout', onElementMouseOut);
-            // Emphasis, normal can be triggered manually by API or other components like hover link.
-            el[method]('emphasis', onElementEmphasisEvent)[method]('normal', onElementNormalEvent);
-            // Also keep previous record.
-            el.__highByOuter = el.__highByOuter || 0;
-
-            el.__highDownDispatcher = !disable;
-        }
+export function setAsHighDownDispatcher(el: Element, asDispatcher: boolean) {
+    const disable = asDispatcher === false;
+    const extendedEl = el as ExtendedDisplayable;
+    // Make `highDownSilentOnTouch` and `highDownOnUpdate` only work after
+    // `setAsHighDownDispatcher` called. Avoid it is modified by user unexpectedly.
+    extendedEl.__highDownSilentOnTouch = extendedEl.highDownSilentOnTouch;
+    extendedEl.__highDownOnUpdate = extendedEl.highDownOnUpdate;
+
+    // Simple optimize, since this method might be
+    // called for each elements of a group in some cases.
+    if (!disable || extendedEl.__highDownDispatcher) {
+        var method: 'on' | 'off' = disable ? 'off' : 'on';
+
+        // Duplicated function will be auto-ignored, see Eventful.js.
+        el[method]('mouseover', onElementMouseOver)[method]('mouseout', onElementMouseOut);
+        // Emphasis, normal can be triggered manually by API or other components like hover link.
+        el[method]('emphasis', onElementEmphasisEvent)[method]('normal', onElementNormalEvent);
+        // Also keep previous record.
+        extendedEl.__highByOuter = extendedEl.__highByOuter || 0;
+
+        extendedEl.__highDownDispatcher = !disable;
     }
 }
 
-export function isHighDownDispatcher(el: Displayable): boolean {
+export function isHighDownDispatcher(el: Element): boolean {
     return !!(el && (el as ExtendedDisplayable).__highDownDispatcher);
 }
 
@@ -802,19 +800,18 @@ export function modifyLabelStyle(
     normalStyleProps?: StyleProps,
     emphasisStyleProps?: StyleProps
 ) {
-    var elStyle = el.style as StyleProps;
+    const extendedEl = el as ExtendedDisplayable;
+    var elStyle = extendedEl.style as StyleProps;
     if (normalStyleProps) {
         rollbackDefaultTextStyle(elStyle);
-        el.setStyle(normalStyleProps);
+        extendedEl.setStyle(normalStyleProps);
         applyDefaultTextStyle(elStyle);
     }
-    if (isExtendedDisplayable(el)) {
-        elStyle = el.__hoverStl;
-        if (emphasisStyleProps && elStyle) {
-            rollbackDefaultTextStyle(elStyle);
-            zrUtil.extend(elStyle, emphasisStyleProps);
-            applyDefaultTextStyle(elStyle);
-        }
+    elStyle = extendedEl.__hoverStl;
+    if (emphasisStyleProps && elStyle) {
+        rollbackDefaultTextStyle(elStyle);
+        zrUtil.extend(elStyle, emphasisStyleProps);
+        applyDefaultTextStyle(elStyle);
     }
 }
 
@@ -1164,12 +1161,12 @@ export function getFont(opt: LabelOption, ecModel: GlobalModel) {
     ].join(' '));
 }
 
-function animateOrSetProps(
+function animateOrSetProps<Props>(
     isUpdate: boolean,
-    el: Displayable,
-    props: DisplayableProps,
+    el: Displayable<Props>,
+    props: Props,
     animatableModel?: Model<AnimationOptionMixin> & {
-        getAnimationDelayParams?: (el: Displayable, dataIndex: number) => AnimationDelayCallbackParam
+        getAnimationDelayParams?: (el: Displayable<Props>, dataIndex: number) => AnimationDelayCallbackParam
     },
     dataIndex?: number,
     cb?: () => void
@@ -1232,9 +1229,9 @@ function animateOrSetProps(
  *         position: [100, 100]
  *     }, seriesModel, function () { console.log('Animation done!'); });
  */
-export function updateProps(
-    el: Displayable,
-    props: DisplayableProps,
+export function updateProps<Props>(
+    el: Displayable<Props>,
+    props: Props,
     // TODO: TYPE AnimatableModel
     animatableModel?: Model<AnimationOptionMixin>,
     dataIndex?: number,
@@ -1251,9 +1248,9 @@ export function updateProps(
  * So do not use this method to one element twice before
  * animation starts, unless you know what you are doing.
  */
-export function initProps(
-    el: Displayable,
-    props: DisplayableProps,
+export function initProps<Props>(
+    el: Displayable<Props>,
+    props: Props,
     animatableModel?: Model<AnimationOptionMixin>,
     dataIndex?: number,
     cb?: () => void
diff --git a/src/util/layout.ts b/src/util/layout.ts
index e5f1985..1faa010 100644
--- a/src/util/layout.ts
+++ b/src/util/layout.ts
@@ -23,7 +23,7 @@ import * as zrUtil from 'zrender/src/core/util';
 import BoundingRect, { RectLike } from 'zrender/src/core/BoundingRect';
 import {parsePercent} from './number';
 import * as formatUtil from './format';
-import { BoxLayoutOptionMixin, ECUnitOption } from './types';
+import { BoxLayoutOptionMixin, ComponentLayoutMode } from './types';
 import { Group } from 'zrender/src/export';
 import Element from 'zrender/src/Element';
 import { Dictionary } from 'zrender/src/core/types';
@@ -332,7 +332,7 @@ export function getLayoutRect(
  *               In this mode positionInfo.width/height can only be number.
  */
 export function positionElement(
-    el:  Element,
+    el: Element,
     positionInfo: BoxLayoutOptionMixin,
     containerRect: RectLike,
     margin: number[] | number,
@@ -417,18 +417,11 @@ export function sizeCalculable(option: BoxLayoutOptionMixin, hvIdx: number): boo
  * @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<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]
-    }
+    opt?: Partial<ComponentLayoutMode>
 ) {
     !zrUtil.isObject(opt) && (opt = {});
 
diff --git a/src/util/model.ts b/src/util/model.ts
index f6a3ee0..b0f45f3 100644
--- a/src/util/model.ts
+++ b/src/util/model.ts
@@ -19,11 +19,19 @@
 
 import * as zrUtil from 'zrender/src/core/util';
 import env from 'zrender/src/core/env';
-import Component from '../model/Component';
 import GlobalModel, { QueryConditionKindB } from '../model/Global';
 import ComponentModel from '../model/Component';
 import List from '../data/List';
-import { Payload, ComponentOption, ComponentMainType, ComponentSubType, DisplayStateHostOption, OptionDataItem, OptionDataPrimitive, TooltipRenderMode } from './types';
+import {
+    Payload,
+    ComponentOption,
+    ComponentMainType,
+    ComponentSubType,
+    DisplayStateHostOption,
+    OptionDataItem,
+    OptionDataPrimitive,
+    TooltipRenderMode
+} from './types';
 import { Dictionary } from 'zrender/src/core/types';
 
 var each = zrUtil.each;
@@ -124,7 +132,7 @@ export function isDataItemOption(dataItem: OptionDataItem): boolean {
         // && !(dataItem[0] && isObject(dataItem[0]) && !(dataItem[0] instanceof Array));
 }
 
-type MappingExistItem = {id?: string, name?: string} | Component;
+type MappingExistItem = {id?: string, name?: string} | ComponentModel;
 interface MappingResultItem<T> {
     exist?: T;
     option?: ComponentOption;
@@ -142,9 +150,9 @@ interface MappingResultItem<T> {
  * Mapping to exists for merge.
  *
  * @public
- * @param {Array.<Object>|Array.<module:echarts/model/Component>} exists
- * @param {Array.<Object>} newCptOptions
- * @return {Array.<Object>} Result, like [{exist: ..., option: ...}, {}],
+ * @param exists
+ * @param newCptOptions
+ * @return Result, like [{exist: ..., option: ...}, {}],
  *                          index of which is the same as exists.
  */
 export function mappingToExists<T extends MappingExistItem>(
diff --git a/src/util/types.ts b/src/util/types.ts
index 6cec92a..26e983b 100644
--- a/src/util/types.ts
+++ b/src/util/types.ts
@@ -51,6 +51,15 @@ export type RendererType = 'canvas' | 'svg';
 
 export type ColorString = string;
 export type ZRColor = ColorString | GradientObject | PatternObject
+export type ZRLineType = 'solid' | 'dotted'
+export type ZRAlign = 'left' | 'center' | 'right'
+export type ZRVerticalAlign = 'top' | 'middle' | 'bottom'
+
+export type ZRFontStyle = 'normal' | 'italic' | 'oblique'
+export type ZRFontWeight = 'normal' | 'bold' | 'bolder' | 'lighter' | number
+
+export type ZREasing = easingType
+
 
 // Actually ComponentFullType is ComponentMainType.ComponentSubType
 // See `checkClassType` check the restict definition.
@@ -447,7 +456,22 @@ export type MediaUnit = {
     option: ECUnitOption
 };
 
+export type ComponentLayoutMode = {
+    // Only support 'box' now.
+    type: 'box',
+    ignoreSize: boolean | [boolean, boolean]
+};
 /******************* Mixins for Common Option Properties   ********************** */
+export interface ColorPaletteOptionMixin {
+    color?: ZRColor | ZRColor[]
+    colorLayer?: ZRColor[][]
+}
+
+export interface LarginOptionMixin {
+    large?: boolean
+    largeThreshold?: number
+}
+
 export interface BoxLayoutOptionMixin {
     width?: number | string;
     height?: number | string;
@@ -456,13 +480,15 @@ export interface BoxLayoutOptionMixin {
     bottom?: number | string;
     left?: number | string;
 }
-export type ComponentLayoutMode = {
-    // Only support 'box' now.
-    type: 'box',
-    ignoreSize: boolean
-};
 
-export type ShadowOptionMixin = {
+export interface CircleLayoutOptionMixin {
+    // Can be percent
+    center?: (number | string)[]
+    // Can specify [innerRadius, outerRadius]
+    radius?: (number | string)[] | number | string
+}
+
+export interface ShadowOptionMixin {
     shadowBlur?: number
     shadowColor?: string
     shadowOffsetX?: number
@@ -476,7 +502,7 @@ export type AnimationDelayCallbackParam = {
 export type AnimationDurationCallback = (idx: number) => number;
 export type AnimationDelayCallback = (idx: number, params?: AnimationDelayCallbackParam) => number;
 
-export type AnimationOptionMixin = {
+export interface AnimationOptionMixin {
     animation?: boolean
     animationThreshold?: number
     // For init animation
@@ -489,27 +515,38 @@ export type AnimationOptionMixin = {
     animationDelayUpdate?: number | AnimationDelayCallback
 }
 
-export type ItemStyleOption = ShadowOptionMixin & {
-    color?: string | GradientObject | PatternObject
+export interface ItemStyleOption extends ShadowOptionMixin {
+    color?: ZRColor
     borderColor?: string
     borderWidth?: number
-    borderType?: 'solid' | 'dotted'
+    borderType?: ZRLineType
     opacity?: number
 }
 
-type TextCommonOption = ShadowOptionMixin & {
+export interface LineStyleOption extends ShadowOptionMixin {
+    width?: number
     color?: string
-    fontStyle?: 'normal' | 'italic' | 'oblique'
-    fontWeight?: 'normal' | 'bold' | 'bolder' | 'lighter' | number
+    opacity?: number
+    type?: ZRLineType
+}
+
+export interface AreaStyleOption extends ShadowOptionMixin {
+    color?: string
+}
+
+interface TextCommonOption extends ShadowOptionMixin {
+    color?: string
+    fontStyle?: ZRFontStyle
+    fontWeight?: ZRFontWeight
     fontFamily?: string
     fontSize?: number
-    align?: 'left' | 'center' | 'right'
-    verticalAlign?: 'top' | 'middle' | 'bottom'
+    align?: ZRAlign
+    verticalAlign?: ZRVerticalAlign
     // @deprecated
-    baseline?: 'top' | 'middle' | 'bottom'
+    baseline?: ZRVerticalAlign
 
     lineHeight?: number
-    backgroundColor?: string | {
+    backgroundColor?: ColorString | {
         image: ImageLike
     }
     borderColor?: string
@@ -530,29 +567,53 @@ type TextCommonOption = ShadowOptionMixin & {
     tag?: string
 }
 
-export type LabelOption = TextCommonOption & {
+export interface LabelOption extends TextCommonOption {
     show?: boolean
     // TODO: TYPE More specified 'inside', 'insideTop'....
     position?: string | number[] | string[]
     distance?: number
-    rotate?: number
+    rotate?: number | boolean
     offset?: number[]
     formatter?: (params: DataParamsUserOutput) => string
 
     rich?: Dictionary<TextCommonOption>
 }
 
+export interface LabelLineOption {
+    show?: boolean
+    length?: number
+    length2?: number
+    smooth?: boolean
+    lineStyle?: LineStyleOption
+}
+
 export interface ComponentOption {
     type?: string;
     id?: string;
     name?: string;
-    // FIXME:TS more
-}
 
-export interface SeriesOption extends ComponentOption{
     z?: number;
     zlevel?: number;
-    data?: any; // FIXME:TS more detail
-    emphasis?: Dictionary<any>;
+    // FIXME:TS more
+}
+
+export interface SeriesOption extends
+    ComponentOption,
+    AnimationOptionMixin,
+    ColorPaletteOptionMixin
+{
+    silent?: boolean
+
+    blendMode?: string
+
+    // Needs to be override
+    data?: unknown;
+
+    legendHoverLink?: boolean
+
+    progressive?: number | false
+    progressiveThreshold?: number
+    progressiveChunkMode?: 'mod'
+
     // FIXME:TS more
 }
diff --git a/src/view/Chart.ts b/src/view/Chart.ts
index 0e2ac7e..a104ca3 100644
--- a/src/view/Chart.ts
+++ b/src/view/Chart.ts
@@ -224,7 +224,7 @@ export type ChartViewConstructor = typeof Chart
     & clazzUtil.ExtendableConstructor
     & clazzUtil.ClassManager;
 
-clazzUtil.enableClassExtend(Chart as ChartViewConstructor, ['dispose'])
+clazzUtil.enableClassExtend(Chart as ChartViewConstructor, ['dispose']);
 clazzUtil.enableClassManagement(Chart as ChartViewConstructor, {registerWhenExtend: true});
 
 
diff --git a/src/view/Component.ts b/src/view/Component.ts
index 0417ccd..f0b3d1e 100644
--- a/src/view/Component.ts
+++ b/src/view/Component.ts
@@ -90,7 +90,7 @@ export type ComponentViewConstructor = typeof Component
     & clazzUtil.ExtendableConstructor
     & clazzUtil.ClassManager;
 
-clazzUtil.enableClassExtend(Component as ComponentViewConstructor)
+clazzUtil.enableClassExtend(Component as ComponentViewConstructor);
 clazzUtil.enableClassManagement(Component as ComponentViewConstructor, {registerWhenExtend: true});
 
 export default Component;


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