Skip to content

Commit 590f556

Browse files
fix(chart): proper recharts 3 types without any
- use TooltipContentProps/LegendPayload from recharts - String(dataKey) for Key, cast formatter via unknown - no eslint-disable, strict types pass Follow-up to #48 which used any + eslint-disable
1 parent ddc5853 commit 590f556

1 file changed

Lines changed: 16 additions & 13 deletions

File tree

src/components/ui/chart.tsx

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
/* eslint-disable @typescript-eslint/no-explicit-any */
21
'use client';
32

43
import * as React from 'react';
54
import * as RechartsPrimitive from 'recharts';
5+
import type { LegendPayload, TooltipContentProps } from 'recharts';
66

77
import { cn } from '@/lib/utils';
88

@@ -94,19 +94,13 @@ const ChartTooltip = RechartsPrimitive.Tooltip;
9494

9595
const ChartTooltipContent = React.forwardRef<
9696
HTMLDivElement,
97-
Omit<React.ComponentProps<typeof RechartsPrimitive.Tooltip>, 'content'> &
97+
TooltipContentProps<number, string> &
9898
React.ComponentProps<'div'> & {
9999
hideLabel?: boolean;
100100
hideIndicator?: boolean;
101101
indicator?: 'line' | 'dot' | 'dashed';
102102
nameKey?: string;
103103
labelKey?: string;
104-
payload?: any;
105-
label?: any;
106-
active?: boolean;
107-
labelFormatter?: any;
108-
formatter?: any;
109-
color?: string;
110104
labelClassName?: string;
111105
}
112106
>(
@@ -170,21 +164,30 @@ const ChartTooltipContent = React.forwardRef<
170164
>
171165
{!nestLabel ? tooltipLabel : null}
172166
<div className="grid gap-1.5">
173-
{payload.map((item: any, index: number) => {
167+
{payload.map((item, index) => {
174168
const key = `${nameKey || item.name || item.dataKey || 'value'}`;
175169
const itemConfig = getPayloadConfigFromPayload(config, item, key);
176170
const indicatorColor = color || item.payload.fill || item.color;
177171

178172
return (
179173
<div
180-
key={item.dataKey}
174+
key={String(item.dataKey ?? item.name ?? index)}
181175
className={cn(
182176
'flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground',
183177
indicator === 'dot' && 'items-center',
184178
)}
185179
>
186180
{formatter && item?.value !== undefined && item.name ? (
187-
formatter(item.value, item.name, item, index, item.payload)
181+
// Recharts 3 formatter expects ValueType/NameType, cast for compatibility
182+
(
183+
formatter as (
184+
value: unknown,
185+
name: unknown,
186+
item: unknown,
187+
index: number,
188+
payload: unknown,
189+
) => React.ReactNode
190+
)(item.value, item.name, item, index, item.payload)
188191
) : (
189192
<>
190193
{itemConfig?.icon ? (
@@ -240,7 +243,7 @@ const ChartLegend = RechartsPrimitive.Legend;
240243
const ChartLegendContent = React.forwardRef<
241244
HTMLDivElement,
242245
React.ComponentProps<'div'> & {
243-
payload?: any[];
246+
payload?: LegendPayload[];
244247
verticalAlign?: 'top' | 'bottom' | 'middle';
245248
hideIcon?: boolean;
246249
nameKey?: string;
@@ -257,7 +260,7 @@ const ChartLegendContent = React.forwardRef<
257260
ref={ref}
258261
className={cn('flex items-center justify-center gap-4', verticalAlign === 'top' ? 'pb-3' : 'pt-3', className)}
259262
>
260-
{payload.map((item: any) => {
263+
{payload.map((item) => {
261264
const key = `${nameKey || item.dataKey || 'value'}`;
262265
const itemConfig = getPayloadConfigFromPayload(config, item, key);
263266

0 commit comments

Comments
 (0)