reactjs - React apache echarts typescript-fel - typen '0' kan inte användas för att indexera typen 'Arrayable'


Jag använder ett e-diagram i React, och jag behöver få en datalängd från LineSeriesOption. Jag gör det på detta sätt:

const dataLen = option.series?.[0].data.length;

Men, jag får ett fel:

[1] src/react_components/e-charts/LineChart.tsx(66,25): error TS7053: Element implicitly has an 'any' type because expression of type '0' can't be used to index type 'Arrayable<LineSeriesOption$1>'.

Detta är den fullständiga koden för komponenten:

import type { LineSeriesOption } from "echarts/charts";
import { LineChart } from "echarts/charts";
import type { GridComponentOption, TitleComponentOption, TooltipComponentOption } from "echarts/components";
import {
    DataZoomComponent,
    GridComponent,
    LegendComponent,
    TitleComponent,
    ToolboxComponent,
    TooltipComponent,
} from "echarts/components";
import type { ComposeOption, ECharts, SetOptionOpts } from "echarts/core";
import { getInstanceByDom, init, use } from "echarts/core";
import { CanvasRenderer } from "echarts/renderers";
import { CSSProperties, ReactNode, useEffect, useRef, useState } from "react";

use([
    LegendComponent,
    LineChart,
    GridComponent,
    TooltipComponent,
    TitleComponent,
    ToolboxComponent,
    DataZoomComponent,
    CanvasRenderer,
]);

export type EChartsOption = ComposeOption<
    LineSeriesOption | TitleComponentOption | GridComponentOption | TooltipComponentOption
>;

export interface ReactEChartsProps {
    option: EChartsOption;
    style?: CSSProperties;
    settings?: SetOptionOpts;
}

let currentIndex = -1;

export function EChartLineChart({ option, style }: ReactEChartsProps): ReactNode {
    const chartRef = useRef<HTMLDivElement | null>(null);
    const [chartInitialized, setChartInitialized] = useState(false);

    useEffect(() => {
        let chart: ECharts | undefined;
        if (chartRef.current !== null) {
            chart = init(chartRef.current as HTMLDivElement);
            setChartInitialized(true);
        }

        function resizeChart() {
            chart?.resize();
        }

        window.addEventListener("resize", resizeChart);

        return () => {
            chart?.dispose();
            window.removeEventListener("resize", resizeChart);
        };
    }, []);

    useEffect(() => {
        const canvas = chartRef.current!.querySelector<HTMLCanvasElement>("canvas");
        const chart = getInstanceByDom(chartRef.current as HTMLDivElement);
        const dataLen = option.series?.[0].data.length;

        const handleKeydown = (e: KeyboardEvent) => {
            if (e.key === "ArrowRight" || e.key === "ArrowLeft") {
                chart?.dispatchAction({
                    type: "downplay",
                    seriesIndex: 0,
                    dataIndex: currentIndex,
                });
                currentIndex =
                    e.key === "ArrowRight"
                        ? (currentIndex + 1) % dataLen
                        : currentIndex <= 0
                        ? dataLen - 1
                        : currentIndex - 1;
                chart?.dispatchAction({
                    type: "highlight",
                    seriesIndex: 0,
                    dataIndex: currentIndex,
                });
                chart?.dispatchAction({
                    type: "showTip",
                    seriesIndex: 0,
                    dataIndex: currentIndex,
                });
            }
        };
        const addKeydownListener = () => window.addEventListener("keydown", handleKeydown);
        const removeKeydownListener = () => window.removeEventListener("keydown", handleKeydown);
        canvas?.setAttribute("tabindex", "0");
        canvas?.addEventListener("focusin", addKeydownListener);
        canvas?.addEventListener("focusout", removeKeydownListener);

        return () => {
            window.removeEventListener("keydown", handleKeydown);
            canvas?.removeEventListener("focusin", addKeydownListener);
            canvas?.removeEventListener("focusout", removeKeydownListener);
        };
    }, [chartInitialized]);

    useEffect(() => {
        if (chartRef.current !== null) {
            const chart = getInstanceByDom(chartRef.current as HTMLDivElement);
            chart!.setOption(option);
        }
    }, [option]);

    return <div ref={chartRef} style={{ width: "100%", height: "250px", ...style }} />;
}

Hur kan jag åtgärda detta TypeScript-fel?

Svar #1

Enligt echarts/types/dist/shared.d.ts

declare type Arrayable<T> = T | T[];

Till exempel betyder Arrayable<number> antingen number eller number[].

Så typen av option.series är LineSeriesOption[] eller LineSeriesOption.

Därför kan du använda typbegränsning för att kontrollera om det är en array eller inte, och sedan komma åt datalängden därefter.

Till exempel:

let dataLen = 0;
if (option.series)
  dataLen = Array.isArray(option.series)
    ? option.series[0].data?.length || 0  // if option.series is an array, use the first element
    : option.series.data?.length || 0;    // if option.series is not an array, use it directly

På så sätt kan du åtgärda felet.

För att lära dig mer, se ECharts dokumentation.

Och du kan se hela exemplet här: codesandbox.io

Relaterade artiklar