echarts icon indicating copy to clipboard operation
echarts copied to clipboard

[Bug] tooltip.formatter option is not typed correctly

Open yay opened this issue 2 years ago • 15 comments

Version

5.4.2

Link to Minimal Reproduction

https://github.com/yay/echarts-tooltip-type-bug

Steps to Reproduce

Uncomment the following piece of code in main.ts in the linked GitHub repo to see the TypeScript error:

// tooltip: {
//   formatter: (params) => {
//     return `${params.name}, ${params.seriesName}`; // BUG: `name` and `seriesName` are unavailable because of incorrect typing
//   },
// },

Current Behavior

Can't access name, seriesName (and other props that are actually populated) in the params object passed to the tooltip formatter function because of incorrect typing echarts exposes.

Expected Behavior

Expected to access name, seriesName and other fields on the params object that are de facto there, but are missing in the declared type.

Environment

- OS: macOS 13.5
- Browser: Chrome 115.0.5790.170 (Official Build) (arm64)
- Framework: echarts 5.4.2 in a vanilla TypeScript app

Any additional comments?

No response

yay avatar Aug 31 '23 12:08 yay

@yay I suggest you use the following workaround, which appears less awkward:

        tooltip: {
            formatter: (params: echarts.DefaultLabelFormatterCallbackParams) => {
                return `${params.name}, ${params.seriesName}`;
            }
        } as echarts.TooltipComponentOption

params is expected to be of type TooltipComponentFormatterCallbackParams which is an alias for

type TopLevelFormatterParams = CallbackDataParams | CallbackDataParams[];

TypeScript will try to infer the most general type from the union that encompasses both possibilities even if you want to infer only CallbackDataParams type. In your case, CallbackDataParams[] is inferred because it's more general than just CallbackDataParams. So, you have to set explicitly that you want CallbackDataParams, which is exported as DefaultLabelFormatterCallbackParams.

As mentioned in the documentation, params can take the form of either an object or an array so I don't think that we should change anything in the library. @plainheart, what are your thoughts on this?

ChepteaCatalin avatar Sep 13 '23 17:09 ChepteaCatalin

@ChepteaCatalin Thanks! Yes, I've already switched to a slightly shorter type since I created this issue, which is similar to your suggestion:

formatter: ((params: echartsTypes.DefaultLabelFormatterCallbackParams[]) => {
  ...
}) as echartsTypes.TooltipComponentOption['formatter'],

yay avatar Sep 15 '23 10:09 yay

@yay, Yes, that is also fine.

@plainheart, should we close this issue?

ChepteaCatalin avatar Sep 15 '23 10:09 ChepteaCatalin

Hi, thanks for this, having the same issue trying to use Typescript with echarts.

I'm still getting an error when trying to access a variable called axisValue.

Property 'axisValue' does not exist on type 'CallbackDataParams'

I can see the value on the object if I log out params but it's not on the type?

Screenshot 2023-09-19 at 09 25 36

kewp avatar Sep 19 '23 03:09 kewp

Sorry if I'm misunderstanding something but I'm also getting this type error (given the solution above):

Type '{ trigger: "axis"; axisPointer: { type: "shadow"; }; formatter: (params: CallbackDataParams[]) => string | TooltipFormatterCallback<TopLevelFormatterParams> | undefined; }' is not assignable to type 'TooltipOption | TooltipOption[] | undefined'.
  Types of property 'formatter' are incompatible.
    Type '(params: CallbackDataParams[]) => string | TooltipFormatterCallback<TopLevelFormatterParams> | undefined' is not assignable to type 'string | TooltipFormatterCallback<TopLevelFormatterParams> | undefined'.
      Type '(params: CallbackDataParams[]) => string | TooltipFormatterCallback<TopLevelFormatterParams> | undefined' is not assignable to type 'TooltipFormatterCallback<TopLevelFormatterParams>'.
        Types of parameters 'params' and 'params' are incompatible.
          Type 'TopLevelFormatterParams' is not assignable to type 'CallbackDataParams[]'.
            Type 'CallbackDataParams' is missing the following properties from type 'CallbackDataParams[]': length, pop, push, concat, and 35 more.ts(2322)

This is how I typed the function:

formatter: function(params: echarts.DefaultLabelFormatterCallbackParams[]) {

kewp avatar Sep 19 '23 04:09 kewp

Sorry if I'm misunderstanding something but I'm also getting this type error (given the solution above):

Type '{ trigger: "axis"; axisPointer: { type: "shadow"; }; formatter: (params: CallbackDataParams[]) => string | TooltipFormatterCallback<TopLevelFormatterParams> | undefined; }' is not assignable to type 'TooltipOption | TooltipOption[] | undefined'.
  Types of property 'formatter' are incompatible.
    Type '(params: CallbackDataParams[]) => string | TooltipFormatterCallback<TopLevelFormatterParams> | undefined' is not assignable to type 'string | TooltipFormatterCallback<TopLevelFormatterParams> | undefined'.
      Type '(params: CallbackDataParams[]) => string | TooltipFormatterCallback<TopLevelFormatterParams> | undefined' is not assignable to type 'TooltipFormatterCallback<TopLevelFormatterParams>'.
        Types of parameters 'params' and 'params' are incompatible.
          Type 'TopLevelFormatterParams' is not assignable to type 'CallbackDataParams[]'.
            Type 'CallbackDataParams' is missing the following properties from type 'CallbackDataParams[]': length, pop, push, concat, and 35 more.ts(2322)

This is how I typed the function:

formatter: function(params: echarts.DefaultLabelFormatterCallbackParams[]) {

Try to type the function as follows:

formatter: function(params: echarts.DefaultLabelFormatterCallbackParams) {

ChepteaCatalin avatar Sep 19 '23 06:09 ChepteaCatalin

@ChepteaCatalin the issue with that is that I'm assuming that params is an array so params[0].axisLabel gives me this error:

Element implicitly has an 'any' type because expression of type '0' can't be used to index type 'CallbackDataParams'.
  Property '0' does not exist on type 'CallbackDataParams'

kewp avatar Sep 19 '23 07:09 kewp

In fact, I'm still getting an error on the function as well:

Type '{ trigger: "axis"; axisPointer: { type: "shadow"; }; formatter: (params: CallbackDataParams) => string | TooltipFormatterCallback<TopLevelFormatterParams> | undefined; }' is not assignable to type 'TooltipOption | TooltipOption[] | undefined'.
  Types of property 'formatter' are incompatible.
    Type '(params: CallbackDataParams) => string | TooltipFormatterCallback<TopLevelFormatterParams> | undefined' is not assignable to type 'string | TooltipFormatterCallback<TopLevelFormatterParams> | undefined'.
      Type '(params: CallbackDataParams) => string | TooltipFormatterCallback<TopLevelFormatterParams> | undefined' is not assignable to type 'TooltipFormatterCallback<TopLevelFormatterParams>'.
        Types of parameters 'params' and 'params' are incompatible.
          Type 'TopLevelFormatterParams' is not assignable to type 'CallbackDataParams'.
            Type 'CallbackDataParams[]' is missing the following properties from type 'CallbackDataParams': componentType, componentSubType, componentIndex, name, and 4 more.ts(2322)
(property) EChartsOption.tooltip?: TooltipComponentOption | TooltipComponentOption[] | undefined

kewp avatar Sep 19 '23 07:09 kewp

@ChepteaCatalin the issue with that is that I'm assuming that params is an array so params[0].axisLabel gives me this error:

Element implicitly has an 'any' type because expression of type '0' can't be used to index type 'CallbackDataParams'.
  Property '0' does not exist on type 'CallbackDataParams'

That's because tooltip formatter params don't have axisLabel property.

ChepteaCatalin avatar Sep 19 '23 07:09 ChepteaCatalin

In fact, I'm still getting an error on the function as well:

Type '{ trigger: "axis"; axisPointer: { type: "shadow"; }; formatter: (params: CallbackDataParams) => string | TooltipFormatterCallback<TopLevelFormatterParams> | undefined; }' is not assignable to type 'TooltipOption | TooltipOption[] | undefined'.
  Types of property 'formatter' are incompatible.
    Type '(params: CallbackDataParams) => string | TooltipFormatterCallback<TopLevelFormatterParams> | undefined' is not assignable to type 'string | TooltipFormatterCallback<TopLevelFormatterParams> | undefined'.
      Type '(params: CallbackDataParams) => string | TooltipFormatterCallback<TopLevelFormatterParams> | undefined' is not assignable to type 'TooltipFormatterCallback<TopLevelFormatterParams>'.
        Types of parameters 'params' and 'params' are incompatible.
          Type 'TopLevelFormatterParams' is not assignable to type 'CallbackDataParams'.
            Type 'CallbackDataParams[]' is missing the following properties from type 'CallbackDataParams': componentType, componentSubType, componentIndex, name, and 4 more.ts(2322)
(property) EChartsOption.tooltip?: TooltipComponentOption | TooltipComponentOption[] | undefined

Try to typecast formatter function as echartsTypes.TooltipComponentOption['formatter'] or typecast the whole tooltip option as echarts.TooltipComponentOption

ChepteaCatalin avatar Sep 19 '23 08:09 ChepteaCatalin

That's because tooltip formatter params don't have axisLabel property.

But I saw the axisLabel on the params object when I log it to console?

It seems like name works (and is the same as axisLabel?) so if I use params[0].name and typecase the whole tooltip as you suggest it fixes the problem. Thank you

kewp avatar Sep 19 '23 08:09 kewp

That's because tooltip formatter params don't have axisLabel property.

But I saw the axisLabel on the params object when I log it to console?

It seems like name works (and is the same as axisLabel?) so if I use params[0].name and typecase the whole tooltip as you suggest it fixes the problem. Thank you

Maybe you want axisValueLabel from params, because I don't see axisLabel in your screenshot and it should not exist there.

ChepteaCatalin avatar Sep 19 '23 08:09 ChepteaCatalin

Maybe you want axisValueLabel from params, because I don't see axisLabel in your screenshot and it should not exist there.

Ah you're right. Sorry, my mistake.

kewp avatar Sep 19 '23 08:09 kewp

Maybe you want axisValueLabel from params, because I don't see axisLabel in your screenshot and it should not exist there.

Ah you're right. Sorry, my mistake.

No worries

ChepteaCatalin avatar Sep 19 '23 08:09 ChepteaCatalin

Got the same error when set params: echarts.DefaultLabelFormatterCallbackParams[]:

Type '{ trigger: "axis"; formatter: (params: echarts.DefaultLabelFormatterCallbackParams[]) => string; appendToBody: true; confine: true; backgroundColor: string; borderColor: string; textStyle: { color: string; }; extraCssText: string; }' is not assignable to type 'Arrayable<TooltipOption> | undefined'.
  Types of property 'formatter' are incompatible.
    Type '(params: echarts.DefaultLabelFormatterCallbackParams[]) => string' is not assignable to type 'string | TooltipFormatterCallback<TopLevelFormatterParams> | undefined'.
      Type '(params: echarts.DefaultLabelFormatterCallbackParams[]) => string' is not assignable to type 'TooltipFormatterCallback<TopLevelFormatterParams>'.
        Types of parameters 'params' and 'params' are incompatible.
          Type 'TopLevelFormatterParams' is not assignable to type 'CallbackDataParams[]'.
            Type 'CallbackDataParams' is missing the following properties from type 'CallbackDataParams[]': length, pop, push, concat, and 35 more.ts

gouku avatar Apr 21 '24 10:04 gouku