Skip to content

Strict tsconfig #6842

Merged
ckifer merged 5 commits intomainfrom
ts-strict
Jan 2, 2026
Merged

Strict tsconfig #6842
ckifer merged 5 commits intomainfrom
ts-strict

Conversation

@PavelVanecek
Copy link
Collaborator

@PavelVanecek PavelVanecek commented Jan 1, 2026

Description

  • Fixed all type problems in src
  • Once that's done, test folder started shining red too because the files import each other
  • So I had to fix test type problems too
  • And then made the tsconfigs extend from a shared base to keep things in sync

Related Issue

#6645

Summary by CodeRabbit

  • Bug Fixes

    • Improved runtime safety across charts: null/undefined guards for interactions, rendering, and resize handling to reduce runtime errors.
    • Safer handling of mixed or missing data shapes to prevent visual glitches.
  • Refactor

    • Tightened typings and exports for several public types and components to improve type safety.
  • Tests & Stories

    • Updated tests and example stories to align with new typings and safer data handling.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 1, 2026

Walkthrough

Adds widespread null/undefined guards and type-narrowing across rendering, interaction, and utility code; introduces several TypeScript signature and export adjustments; and updates project tsconfig files to centralize strict compiler options while selectively relaxing them for tests and Storybook.

Changes

Cohort / File(s) Summary
Null-safety in cartesian interactions
src/cartesian/Brush.tsx
Added null guards for touch/drag/keyboard handlers and range computations to avoid dereferencing null/undefined.
Null-safety in cartesian rendering
src/cartesian/CartesianGrid.tsx, src/cartesian/Line.tsx, src/cartesian/ReferenceLine.tsx
Replaced falsy checks with explicit null checks; guarded array indexing and destructuring of points/lines.
YAxis declaration change
src/cartesian/YAxis.tsx
Converted YAxisImpl from a typed FunctionComponent constant to a plain function; removed isValidElement from imports (undefined reference introduced).
Funnel data handling
src/cartesian/Funnel.tsx
Normalizes numeric values, handles scalar and ranged (array) data shapes, and guards payload width omission with type checks.
Axis tick computation
src/cartesian/getEquidistantTicks.ts, src/cartesian/getTicks.ts
Skip null entries in tick computations, preserve initial entries for size calculations, and guard sign/tail logic.
Pie & polar typing
src/polar/Pie.tsx, src/polar/PolarRadiusAxis.tsx
Defaulted startAngle fallback and added explicit reduce typing for extent calculations.
Scale factory overloads
src/util/scale/RechartsScale.ts
Added multiple TypeScript overloads for rechartsScaleFactory to support various scale input types.
Axis scale type expansion
src/state/cartesianAxisSlice.ts
Broadened BaseCartesianAxis.scale union to include specialized CustomScaleDefinition variants (string/number/Date); removed undefined.
RechartsWrapper refactor
src/chart/RechartsWrapper.tsx
Removed isPercent usage; branch on string vs number widths; added StaticDivProps; guarded ResizeObserver entries.
Tooltip payload searchers
src/chart/Sankey.tsx, src/chart/SunburstChart.tsx, src/state/optionsSlice.ts
Loosened parameter types to unknown with runtime guards (null/object/array checks); unified to TooltipPayloadSearcher where applicable.
Treemap type safety
src/chart/Treemap.tsx
Changed node index signature to unknown, added isTreemapNode guard, adjusted payload/searcher signatures, and hardened value extraction.
Tooltip & LabelList types
src/component/Tooltip.tsx, src/component/LabelList.tsx
Aligned tooltip payload uniq typing to TooltipPayloadEntry; introduced/exported LabelListEntry; tightened dataKey generics and payload typing.
Utility and container guards
src/util/ChartUtils.ts, src/component/ResponsiveContainer.tsx
getValueByDataKey accepts null/undefined obj; ResizeObserver callbacks now guard first entry before using contentRect.
Curve typing refinements
src/shape/Curve.tsx
Renamed d3 imports, added explicit getCurveFactory return type, and introduced typed local curve functions (with ts-expect-error workarounds).
TypeScript configuration
tsconfig.base.json, tsconfig.json, storybook/tsconfig.json, test/tsconfig.json
Added tsconfig.base.json with strict options; other configs extend/override it and selectively disable noUncheckedIndexedAccess for Storybook/tests.
Test helpers & matchers
test/helper/createSelectorTestCase.tsx, test/helper/expectStackGroups.ts, test/helper/toBeRechartsScale.ts
Simplified selector typing, introduced SyncExpectationResult, and made matcher return/message types more robust.
Test typings and adjustments
test/... (multiple)
Broadened/loosened test prop types (labels, positions), removed some ts-expect-error suppressions, added as const where needed, and updated imports to reflect new/public types (e.g., LabelProps, FunnelTrapezoidItem, TreemapNode).
Public exports updated
src/index.ts
Re-exported LabelListEntry type from component/LabelList.
WWW/storybook usages
www/..., storybook/stories/...
Updated story and example code to import and use new public types (e.g., LabelProps, TreemapNode); added safe checks for optional children lengths.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

typescript

Suggested reviewers

  • ckifer

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 3.33% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Description check ❓ Inconclusive The PR description addresses the key changes: fixing type problems in src and test folders, and implementing shared tsconfig. However, it does not follow the provided template structure with sections like Motivation and Context, How Has This Been Tested, or Types of Changes. Expand the description to include template sections: explain why strict tsconfig is needed, detail testing approach, and mark the appropriate change type checkbox to ensure all reviewers understand the impact and validation.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: enabling strict TypeScript configuration (tsconfig) across the project. It is concise and specific enough for teammates scanning history to understand the primary change.
✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (5)
test/helper/expectStackGroups.ts (4)

59-59: Add explicit return type annotation.

The function rechartsStackedDataMatcher lacks an explicit return type annotation, while the other two matcher functions have them. This violates the coding guidelines requiring explicit typing.

🔎 Proposed fix
-function rechartsStackedDataMatcher(received: ExpectedStackedData, expected: ExpectedStackedData) {
+function rechartsStackedDataMatcher(
+  received: ExpectedStackedData,
+  expected: ExpectedStackedData,
+): { pass: boolean; message: () => string } {

As per coding guidelines: "Type function parameters and return values explicitly in TypeScript, do not rely on implicit any or inference; exceptions are React components and trivial functions"


66-73: Critical: message must be a function, not a string.

The return type requires message: () => string, but line 71 assigns a string directly. This violates the Vitest matcher API contract and will cause a runtime error when Vitest attempts to call .message() to display the error.

🔎 Proposed fix
     return {
       pass: false,
-      message: e instanceof Error ? e.message : String(e),
+      message: () => (e instanceof Error ? e.message : String(e)),
     };

86-93: Critical: message must be a function, not a string.

The return type requires message: () => string, but line 91 assigns a string directly. This violates the Vitest matcher API contract and will cause a runtime error when Vitest attempts to call .message() to display the error.

🔎 Proposed fix
     return {
       pass: false,
-      message: e instanceof Error ? e.message : String(e),
+      message: () => (e instanceof Error ? e.message : String(e)),
     };

109-116: Critical: message must be a function, not a string.

The return type requires message: () => string, but line 114 assigns a string directly. This violates the Vitest matcher API contract and will cause a runtime error when Vitest attempts to call .message() to display the error.

🔎 Proposed fix
     return {
       pass: false,
-      message: e instanceof Error ? e.message : String(e),
+      message: () => (e instanceof Error ? e.message : String(e)),
     };
src/shape/Curve.tsx (1)

251-262: Fix type mismatch: lineFunction should accept both D3AreaCurve and D3LineCurve.

The variable declared on line 252 as D3LineCurve<Coordinate> is assigned D3AreaCurve on lines 254 and 256 (from shapeArea()), but only D3LineCurve on line 258 (from shapeLine()). Either declare lineFunction as D3AreaCurve<Coordinate> | D3LineCurve<Coordinate> or verify why these types are compatible. The @ts-expect-error on line 261 only suppresses the .defined().curve() chain error, not the assignment mismatch on lines 254/256.

🧹 Nitpick comments (2)
src/chart/RechartsWrapper.tsx (1)

200-215: Logic is correct; consider cleaner prop spreading.

The refactored logic correctly handles three cases:

  1. String dimensions (percentages, CSS values) → read from DOM
  2. Numeric dimensions → use directly
  3. Undefined dimensions → render without SVG (backwards compatibility)

The type narrowing flow is sound and improves on the previous isPercent-based approach.

Optional: Cleaner prop spreading for StaticDiv

On line 206, spreading {...props} includes width and height with broader types before overriding. Consider destructuring to omit them:

 const NonResponsiveDiv = forwardRef<HTMLDivElement, WrapperDivProps>((props: WrapperDivProps, ref): ReactNode => {
-  const { width, height } = props;
+  const { width, height, ...rest } = props;
   // When width or height are percentages or CSS short names, read size from DOM once
   if (typeof width === 'string' || typeof height === 'string') {
     return <ReadSizeOnceDiv {...props} ref={ref} />;
   }
   // When both are numbers, use them directly
   if (typeof width === 'number' && typeof height === 'number') {
-    return <StaticDiv {...props} width={width} height={height} ref={ref} />;
+    return <StaticDiv {...rest} width={width} height={height} ref={ref} />;
   }
   // When width/height are undefined, render wrapper div without reporting size

This avoids passing width/height twice and makes the type compatibility explicit.

src/cartesian/Funnel.tsx (1)

596-623: Consider simplifying the ranged value logic.

The nested conditionals for handling nextVal as either a scalar or array are correct but complex. The control flow ensures nextVal ends up as number | undefined, yet the @ts-expect-error on line 630 suggests uncertainty about its type.

Given the branching, nextVal should always resolve to a number (or undefined transiently) by the time line 631 executes. You could add a type assertion or refactor to make this clearer, but the current logic is functionally correct.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f54934b and 7ea742c.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (43)
  • src/cartesian/Brush.tsx
  • src/cartesian/CartesianGrid.tsx
  • src/cartesian/Funnel.tsx
  • src/cartesian/Line.tsx
  • src/cartesian/ReferenceLine.tsx
  • src/cartesian/YAxis.tsx
  • src/cartesian/getEquidistantTicks.ts
  • src/cartesian/getTicks.ts
  • src/chart/RechartsWrapper.tsx
  • src/chart/Sankey.tsx
  • src/chart/SunburstChart.tsx
  • src/chart/Treemap.tsx
  • src/component/LabelList.tsx
  • src/component/ResponsiveContainer.tsx
  • src/component/Text.tsx
  • src/component/Tooltip.tsx
  • src/polar/Pie.tsx
  • src/polar/PolarRadiusAxis.tsx
  • src/shape/Curve.tsx
  • src/state/cartesianAxisSlice.ts
  • src/state/optionsSlice.ts
  • src/util/ChartUtils.ts
  • src/util/scale/RechartsScale.ts
  • storybook/tsconfig.json
  • test/cartesian/Area.spec.tsx
  • test/cartesian/Bar.spec.tsx
  • test/cartesian/Brush.stacked.spec.tsx
  • test/cartesian/ErrorBar.spec.tsx
  • test/cartesian/Funnel.spec.tsx
  • test/cartesian/Scatter.spec.tsx
  • test/cartesian/XAxis/XAxis.vertical.spec.tsx
  • test/cartesian/YAxis/YAxis.spec.tsx
  • test/chart/LineChart.spec.tsx
  • test/helper/createSelectorTestCase.tsx
  • test/helper/expectStackGroups.ts
  • test/helper/toBeRechartsScale.ts
  • test/polar/PolarGrid.spec.tsx
  • test/state/optionsSlice.spec.ts
  • test/state/selectors/pieSelectors.spec.tsx
  • test/state/selectors/selectors.spec.tsx
  • test/tsconfig.json
  • tsconfig.base.json
  • tsconfig.json
💤 Files with no reviewable changes (3)
  • test/cartesian/Brush.stacked.spec.tsx
  • test/state/selectors/pieSelectors.spec.tsx
  • test/state/optionsSlice.spec.ts
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

**/*.{ts,tsx}: Never use any type (implicit or explicit) in TypeScript code
Prefer unknown over any and refine the type in TypeScript
Type function parameters and return values explicitly in TypeScript, do not rely on implicit any or inference; exceptions are React components and trivial functions
Do not use as type assertions in TypeScript; the only exception is as const

All imports from recharts must use the public API entry point (e.g., import { TooltipIndex } from 'recharts'). Imports from internal paths like recharts/types/* or recharts/src/* are not allowed and will fail the linter.

Files:

  • test/chart/LineChart.spec.tsx
  • src/component/ResponsiveContainer.tsx
  • src/polar/PolarRadiusAxis.tsx
  • test/helper/expectStackGroups.ts
  • src/component/LabelList.tsx
  • test/cartesian/Scatter.spec.tsx
  • src/cartesian/ReferenceLine.tsx
  • src/chart/SunburstChart.tsx
  • src/component/Text.tsx
  • src/cartesian/CartesianGrid.tsx
  • test/polar/PolarGrid.spec.tsx
  • test/cartesian/Funnel.spec.tsx
  • src/cartesian/getEquidistantTicks.ts
  • src/component/Tooltip.tsx
  • test/state/selectors/selectors.spec.tsx
  • src/cartesian/Brush.tsx
  • src/cartesian/Funnel.tsx
  • src/cartesian/Line.tsx
  • src/chart/Sankey.tsx
  • test/cartesian/XAxis/XAxis.vertical.spec.tsx
  • src/cartesian/getTicks.ts
  • src/state/optionsSlice.ts
  • src/polar/Pie.tsx
  • src/shape/Curve.tsx
  • test/helper/createSelectorTestCase.tsx
  • test/cartesian/Area.spec.tsx
  • src/util/scale/RechartsScale.ts
  • test/cartesian/ErrorBar.spec.tsx
  • src/chart/RechartsWrapper.tsx
  • src/cartesian/YAxis.tsx
  • src/state/cartesianAxisSlice.ts
  • test/cartesian/YAxis/YAxis.spec.tsx
  • test/cartesian/Bar.spec.tsx
  • test/helper/toBeRechartsScale.ts
  • src/chart/Treemap.tsx
  • src/util/ChartUtils.ts
test/**/*.spec.{ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Aim for 100% unit test code coverage when writing new code

Files:

  • test/chart/LineChart.spec.tsx
  • test/cartesian/Scatter.spec.tsx
  • test/polar/PolarGrid.spec.tsx
  • test/cartesian/Funnel.spec.tsx
  • test/state/selectors/selectors.spec.tsx
  • test/cartesian/XAxis/XAxis.vertical.spec.tsx
  • test/cartesian/Area.spec.tsx
  • test/cartesian/ErrorBar.spec.tsx
  • test/cartesian/YAxis/YAxis.spec.tsx
  • test/cartesian/Bar.spec.tsx
**/*.{js,ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Ensure code lints by running npm run lint and follows Airbnb's Style Guide

Files:

  • test/chart/LineChart.spec.tsx
  • src/component/ResponsiveContainer.tsx
  • src/polar/PolarRadiusAxis.tsx
  • test/helper/expectStackGroups.ts
  • src/component/LabelList.tsx
  • test/cartesian/Scatter.spec.tsx
  • src/cartesian/ReferenceLine.tsx
  • src/chart/SunburstChart.tsx
  • src/component/Text.tsx
  • src/cartesian/CartesianGrid.tsx
  • test/polar/PolarGrid.spec.tsx
  • test/cartesian/Funnel.spec.tsx
  • src/cartesian/getEquidistantTicks.ts
  • src/component/Tooltip.tsx
  • test/state/selectors/selectors.spec.tsx
  • src/cartesian/Brush.tsx
  • src/cartesian/Funnel.tsx
  • src/cartesian/Line.tsx
  • src/chart/Sankey.tsx
  • test/cartesian/XAxis/XAxis.vertical.spec.tsx
  • src/cartesian/getTicks.ts
  • src/state/optionsSlice.ts
  • src/polar/Pie.tsx
  • src/shape/Curve.tsx
  • test/helper/createSelectorTestCase.tsx
  • test/cartesian/Area.spec.tsx
  • src/util/scale/RechartsScale.ts
  • test/cartesian/ErrorBar.spec.tsx
  • src/chart/RechartsWrapper.tsx
  • src/cartesian/YAxis.tsx
  • src/state/cartesianAxisSlice.ts
  • test/cartesian/YAxis/YAxis.spec.tsx
  • test/cartesian/Bar.spec.tsx
  • test/helper/toBeRechartsScale.ts
  • src/chart/Treemap.tsx
  • src/util/ChartUtils.ts
test/**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (test/README.md)

test/**/*.{test,spec}.{ts,tsx}: Aim for 100% unit test code coverage when writing new code
Prefer to use the createSelectorTestCase helper function when writing or modifying tests
Use the expectLastCalledWith helper function instead of expect(spy).toHaveBeenLastCalledWith(...) for better typing and autocompletion
Verify the number of selector calls using the spy object from createSelectorTestCase to spot unnecessary re-renders and improve performance
Mock getBoundingClientRect in tests using the helper function provided in test/helper/MockGetBoundingClientRect.ts
Use vi.useFakeTimers() in all tests due to Redux autoBatchEnhancer dependency on timers and requestAnimationFrame
Call vi.runOnlyPendingTimers() to advance timers after renders when not using createSelectorTestCase helper, and avoid vi.runAllTimers() to prevent infinite loops
Use userEvent.setup({ advanceTimers: vi.runOnlyPendingTimers }) or the userEventSetup helper function from test/helper/userEventSetup.ts when creating userEvent instances
When testing tooltips on hover, use vi.runOnlyPendingTimers() after each userEvent.hover() call or use the showTooltip helper function from tooltipTestHelpers.ts to account for requestAnimationFrame delays

Files:

  • test/chart/LineChart.spec.tsx
  • test/cartesian/Scatter.spec.tsx
  • test/polar/PolarGrid.spec.tsx
  • test/cartesian/Funnel.spec.tsx
  • test/state/selectors/selectors.spec.tsx
  • test/cartesian/XAxis/XAxis.vertical.spec.tsx
  • test/cartesian/Area.spec.tsx
  • test/cartesian/ErrorBar.spec.tsx
  • test/cartesian/YAxis/YAxis.spec.tsx
  • test/cartesian/Bar.spec.tsx
**/*.spec.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

When running unit tests, prefer to run a single test file using npm run test -- path/to/TestFile.spec.tsx rather than running all tests with npm test

Unit tests should be placed in the test directory, with some tests also allowed in www/test. Test files follow the naming convention *.spec.tsx.

Files:

  • test/chart/LineChart.spec.tsx
  • test/cartesian/Scatter.spec.tsx
  • test/polar/PolarGrid.spec.tsx
  • test/cartesian/Funnel.spec.tsx
  • test/state/selectors/selectors.spec.tsx
  • test/cartesian/XAxis/XAxis.vertical.spec.tsx
  • test/cartesian/Area.spec.tsx
  • test/cartesian/ErrorBar.spec.tsx
  • test/cartesian/YAxis/YAxis.spec.tsx
  • test/cartesian/Bar.spec.tsx
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Do not hardcode any strings or formatting choices in library code; users should provide localized strings as desired

Files:

  • src/component/ResponsiveContainer.tsx
  • src/polar/PolarRadiusAxis.tsx
  • src/component/LabelList.tsx
  • src/cartesian/ReferenceLine.tsx
  • src/chart/SunburstChart.tsx
  • src/component/Text.tsx
  • src/cartesian/CartesianGrid.tsx
  • src/cartesian/getEquidistantTicks.ts
  • src/component/Tooltip.tsx
  • src/cartesian/Brush.tsx
  • src/cartesian/Funnel.tsx
  • src/cartesian/Line.tsx
  • src/chart/Sankey.tsx
  • src/cartesian/getTicks.ts
  • src/state/optionsSlice.ts
  • src/polar/Pie.tsx
  • src/shape/Curve.tsx
  • src/util/scale/RechartsScale.ts
  • src/chart/RechartsWrapper.tsx
  • src/cartesian/YAxis.tsx
  • src/state/cartesianAxisSlice.ts
  • src/chart/Treemap.tsx
  • src/util/ChartUtils.ts
🧠 Learnings (31)
📓 Common learnings
Learnt from: CR
Repo: recharts/recharts PR: 0
File: DEVELOPING.md:0-0
Timestamp: 2025-12-26T15:59:11.254Z
Learning: Applies to **/*.{ts,tsx} : All imports from `recharts` must use the public API entry point (e.g., `import { TooltipIndex } from 'recharts'`). Imports from internal paths like `recharts/types/*` or `recharts/src/*` are not allowed and will fail the linter.
Learnt from: CR
Repo: recharts/recharts PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-25T01:22:59.729Z
Learning: Applies to **/*.{ts,tsx} : Type function parameters and return values explicitly in TypeScript, do not rely on implicit any or inference; exceptions are React components and trivial functions
Learnt from: PavelVanecek
Repo: recharts/recharts PR: 6669
File: www/src/docs/exampleComponents/ScatterChart/ScatterChartWithLabels.tsx:2-2
Timestamp: 2025-11-23T13:30:10.395Z
Learning: The `TooltipIndex` type from recharts is defined in `src/state/tooltipSlice.ts` but is not currently exported from the public API entry points. It should not be imported from `recharts/types/state/tooltipSlice` as this is an internal implementation path. An ESLint rule is needed to prevent regressions.
📚 Learning: 2025-12-16T08:12:06.809Z
Learnt from: PavelVanecek
Repo: recharts/recharts PR: 6783
File: test/util/ChartUtils.spec.tsx:15-16
Timestamp: 2025-12-16T08:12:06.809Z
Learning: In tests (files under any test directory, e.g., test/, __tests__/, etc.), allow importing internal module paths (e.g., ../../src/...) and do not require imports to use the public API entry point (src/index.ts). The public API import restriction should apply only to non-test code. During reviews, accept internal imports in test files and enforce the public API pattern only for non-test code.

Applied to files:

  • test/chart/LineChart.spec.tsx
  • test/cartesian/Scatter.spec.tsx
  • test/polar/PolarGrid.spec.tsx
  • test/cartesian/Funnel.spec.tsx
  • test/state/selectors/selectors.spec.tsx
  • test/cartesian/XAxis/XAxis.vertical.spec.tsx
  • test/helper/createSelectorTestCase.tsx
  • test/cartesian/Area.spec.tsx
  • test/cartesian/ErrorBar.spec.tsx
  • test/cartesian/YAxis/YAxis.spec.tsx
  • test/cartesian/Bar.spec.tsx
📚 Learning: 2025-11-19T14:08:01.728Z
Learnt from: PavelVanecek
Repo: recharts/recharts PR: 6659
File: www/src/components/GuideView/Performance/index.tsx:232-250
Timestamp: 2025-11-19T14:08:01.728Z
Learning: In Recharts version 3.4.2, object-as-prop optimizations were introduced to reduce unnecessary re-renders when new object references are passed as props. This affects the recommendation for the `react-perf/jsx-no-new-object-as-prop` ESLint rule.

Applied to files:

  • test/chart/LineChart.spec.tsx
  • src/chart/RechartsWrapper.tsx
  • test/helper/toBeRechartsScale.ts
📚 Learning: 2025-12-26T15:59:11.254Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: DEVELOPING.md:0-0
Timestamp: 2025-12-26T15:59:11.254Z
Learning: For release testing, use `yalc` to test Recharts changes in a test package as close as possible to the results of `npm publish` to ensure no unintended breaking changes are published.

Applied to files:

  • test/chart/LineChart.spec.tsx
📚 Learning: 2025-11-25T01:23:08.250Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.250Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : Verify the number of selector calls using the spy object from `createSelectorTestCase` to spot unnecessary re-renders and improve performance

Applied to files:

  • test/chart/LineChart.spec.tsx
  • test/helper/expectStackGroups.ts
  • test/cartesian/Scatter.spec.tsx
  • test/polar/PolarGrid.spec.tsx
  • test/cartesian/Funnel.spec.tsx
  • test/state/selectors/selectors.spec.tsx
  • test/cartesian/XAxis/XAxis.vertical.spec.tsx
  • test/helper/createSelectorTestCase.tsx
  • test/cartesian/Area.spec.tsx
  • test/cartesian/ErrorBar.spec.tsx
  • test/helper/toBeRechartsScale.ts
📚 Learning: 2025-12-26T15:59:11.254Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: DEVELOPING.md:0-0
Timestamp: 2025-12-26T15:59:11.254Z
Learning: Applies to **/*.{ts,tsx} : All imports from `recharts` must use the public API entry point (e.g., `import { TooltipIndex } from 'recharts'`). Imports from internal paths like `recharts/types/*` or `recharts/src/*` are not allowed and will fail the linter.

Applied to files:

  • test/chart/LineChart.spec.tsx
  • src/chart/SunburstChart.tsx
  • test/cartesian/Funnel.spec.tsx
  • src/component/Tooltip.tsx
  • test/tsconfig.json
  • src/chart/Sankey.tsx
  • src/state/optionsSlice.ts
  • test/cartesian/ErrorBar.spec.tsx
  • src/chart/RechartsWrapper.tsx
  • src/cartesian/YAxis.tsx
  • test/helper/toBeRechartsScale.ts
  • src/chart/Treemap.tsx
📚 Learning: 2025-12-08T08:23:26.261Z
Learnt from: PavelVanecek
Repo: recharts/recharts PR: 6750
File: src/state/selectors/axisSelectors.ts:593-602
Timestamp: 2025-12-08T08:23:26.261Z
Learning: In the recharts codebase, `DataKey<any>` is an intentional exception to the "no any" rule while proper typing is being developed. This should not be flagged in reviews.

Applied to files:

  • test/chart/LineChart.spec.tsx
  • src/component/LabelList.tsx
  • test/cartesian/YAxis/YAxis.spec.tsx
  • src/util/ChartUtils.ts
📚 Learning: 2025-11-25T01:23:08.250Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.250Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : Use the `expectLastCalledWith` helper function instead of `expect(spy).toHaveBeenLastCalledWith(...)` for better typing and autocompletion

Applied to files:

  • test/chart/LineChart.spec.tsx
  • test/helper/expectStackGroups.ts
  • test/state/selectors/selectors.spec.tsx
  • test/cartesian/XAxis/XAxis.vertical.spec.tsx
  • test/cartesian/Area.spec.tsx
  • test/cartesian/ErrorBar.spec.tsx
  • test/helper/toBeRechartsScale.ts
📚 Learning: 2025-12-14T13:58:49.197Z
Learnt from: PavelVanecek
Repo: recharts/recharts PR: 6771
File: src/shape/Curve.tsx:39-40
Timestamp: 2025-12-14T13:58:49.197Z
Learning: In the recharts codebase, hooks like useAppSelector and other hooks (e.g., useChartLayout()) return undefined when used outside Redux Provider context, instead of throwing. This enables components that call these hooks, such as Curve, to operate in standalone mode by falling back to prop values. During code reviews, ensure TSX files gracefully handle undefined results from hooks and implement fallbacks (e.g., via default props or explicit prop-based values) rather than assuming the hook is always within Provider.

Applied to files:

  • src/component/ResponsiveContainer.tsx
  • src/polar/PolarRadiusAxis.tsx
  • src/component/LabelList.tsx
  • src/cartesian/ReferenceLine.tsx
  • src/chart/SunburstChart.tsx
  • src/component/Text.tsx
  • src/cartesian/CartesianGrid.tsx
  • src/component/Tooltip.tsx
  • src/cartesian/Brush.tsx
  • src/cartesian/Funnel.tsx
  • src/cartesian/Line.tsx
  • src/chart/Sankey.tsx
  • src/polar/Pie.tsx
  • src/shape/Curve.tsx
  • src/chart/RechartsWrapper.tsx
  • src/cartesian/YAxis.tsx
  • src/chart/Treemap.tsx
📚 Learning: 2025-11-23T13:30:10.395Z
Learnt from: PavelVanecek
Repo: recharts/recharts PR: 6669
File: www/src/docs/exampleComponents/ScatterChart/ScatterChartWithLabels.tsx:2-2
Timestamp: 2025-11-23T13:30:10.395Z
Learning: The `TooltipIndex` type from recharts is defined in `src/state/tooltipSlice.ts` but is not currently exported from the public API entry points. It should not be imported from `recharts/types/state/tooltipSlice` as this is an internal implementation path. An ESLint rule is needed to prevent regressions.

Applied to files:

  • src/polar/PolarRadiusAxis.tsx
  • src/chart/SunburstChart.tsx
  • src/component/Tooltip.tsx
  • test/state/selectors/selectors.spec.tsx
  • src/chart/Sankey.tsx
  • src/state/optionsSlice.ts
  • test/helper/createSelectorTestCase.tsx
  • src/chart/RechartsWrapper.tsx
  • src/state/cartesianAxisSlice.ts
  • test/helper/toBeRechartsScale.ts
  • src/chart/Treemap.tsx
📚 Learning: 2025-12-16T08:12:13.355Z
Learnt from: PavelVanecek
Repo: recharts/recharts PR: 6783
File: test/util/ChartUtils.spec.tsx:15-16
Timestamp: 2025-12-16T08:12:13.355Z
Learning: In the recharts codebase, files in the `test` folder are allowed to import from internal paths (e.g., `../../src/state/cartesianAxisSlice`) and do not need to use the public API entry point (`src/index.ts`). The public API import restriction applies only to non-test code.

Applied to files:

  • src/polar/PolarRadiusAxis.tsx
  • test/helper/expectStackGroups.ts
  • test/tsconfig.json
  • src/chart/RechartsWrapper.tsx
  • src/cartesian/YAxis.tsx
  • src/state/cartesianAxisSlice.ts
📚 Learning: 2025-11-25T01:22:59.729Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-25T01:22:59.729Z
Learning: Applies to **/*.{ts,tsx} : Type function parameters and return values explicitly in TypeScript, do not rely on implicit any or inference; exceptions are React components and trivial functions

Applied to files:

  • src/polar/PolarRadiusAxis.tsx
  • tsconfig.json
  • test/state/selectors/selectors.spec.tsx
  • test/tsconfig.json
  • test/cartesian/Area.spec.tsx
  • tsconfig.base.json
  • src/chart/Treemap.tsx
📚 Learning: 2025-11-25T01:23:08.250Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.250Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : Prefer to use the `createSelectorTestCase` helper function when writing or modifying tests

Applied to files:

  • test/helper/expectStackGroups.ts
  • test/state/selectors/selectors.spec.tsx
  • test/tsconfig.json
  • test/cartesian/XAxis/XAxis.vertical.spec.tsx
  • test/helper/createSelectorTestCase.tsx
  • test/cartesian/Area.spec.tsx
  • test/cartesian/ErrorBar.spec.tsx
  • test/helper/toBeRechartsScale.ts
📚 Learning: 2025-11-25T01:22:59.729Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-25T01:22:59.729Z
Learning: Applies to **/*.{ts,tsx} : Do not use `as` type assertions in TypeScript; the only exception is `as const`

Applied to files:

  • tsconfig.json
  • test/tsconfig.json
  • test/cartesian/ErrorBar.spec.tsx
  • storybook/tsconfig.json
  • tsconfig.base.json
📚 Learning: 2025-11-25T01:22:59.729Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-25T01:22:59.729Z
Learning: Applies to **/*.{ts,tsx} : Prefer `unknown` over `any` and refine the type in TypeScript

Applied to files:

  • tsconfig.json
  • test/tsconfig.json
  • src/state/optionsSlice.ts
  • storybook/tsconfig.json
  • tsconfig.base.json
📚 Learning: 2025-11-25T01:22:59.729Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-25T01:22:59.729Z
Learning: Applies to **/*.{ts,tsx} : Never use `any` type (implicit or explicit) in TypeScript code

Applied to files:

  • tsconfig.json
  • tsconfig.base.json
📚 Learning: 2025-11-25T01:22:59.729Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-25T01:22:59.729Z
Learning: Applies to **/*.{js,ts,tsx} : Ensure code lints by running `npm run lint` and follows Airbnb's Style Guide

Applied to files:

  • tsconfig.json
📚 Learning: 2025-11-25T01:22:59.729Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-25T01:22:59.729Z
Learning: Applies to test/**/*.spec.{ts,tsx} : Aim for 100% unit test code coverage when writing new code

Applied to files:

  • tsconfig.json
📚 Learning: 2025-12-26T15:59:11.254Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: DEVELOPING.md:0-0
Timestamp: 2025-12-26T15:59:11.254Z
Learning: Applies to test-vr/**/*.spec.ts : Visual regression tests should follow the naming convention `*.spec.ts` and be placed in the `test-vr` directory. When updating snapshots, new files created in `test-vr/__snapshots__` should be committed to the repository.

Applied to files:

  • test/polar/PolarGrid.spec.tsx
📚 Learning: 2025-11-25T01:22:59.729Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-25T01:22:59.729Z
Learning: Applies to test/component/**/*.spec.tsx : Use React Testing Library for testing component interactions and behavior upon rendering

Applied to files:

  • test/cartesian/Funnel.spec.tsx
  • test/state/selectors/selectors.spec.tsx
  • test/tsconfig.json
  • test/cartesian/XAxis/XAxis.vertical.spec.tsx
  • test/helper/createSelectorTestCase.tsx
  • test/cartesian/Area.spec.tsx
  • test/cartesian/ErrorBar.spec.tsx
  • src/cartesian/YAxis.tsx
📚 Learning: 2025-11-25T01:23:08.250Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.250Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : When testing tooltips on hover, use `vi.runOnlyPendingTimers()` after each `userEvent.hover()` call or use the `showTooltip` helper function from `tooltipTestHelpers.ts` to account for requestAnimationFrame delays

Applied to files:

  • test/cartesian/Funnel.spec.tsx
  • test/state/selectors/selectors.spec.tsx
  • test/cartesian/ErrorBar.spec.tsx
📚 Learning: 2025-11-25T01:23:08.250Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.250Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : Call `vi.runOnlyPendingTimers()` to advance timers after renders when not using `createSelectorTestCase` helper, and avoid `vi.runAllTimers()` to prevent infinite loops

Applied to files:

  • test/state/selectors/selectors.spec.tsx
  • test/helper/createSelectorTestCase.tsx
  • test/cartesian/ErrorBar.spec.tsx
📚 Learning: 2025-12-26T15:59:11.254Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: DEVELOPING.md:0-0
Timestamp: 2025-12-26T15:59:11.254Z
Learning: Applies to **/*.spec.{ts,tsx} : Unit tests should be placed in the `test` directory, with some tests also allowed in `www/test`. Test files follow the naming convention `*.spec.tsx`.

Applied to files:

  • test/tsconfig.json
  • test/cartesian/Area.spec.tsx
📚 Learning: 2025-11-25T01:23:08.250Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.250Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : Use `vi.useFakeTimers()` in all tests due to Redux autoBatchEnhancer dependency on timers and `requestAnimationFrame`

Applied to files:

  • test/tsconfig.json
  • test/cartesian/ErrorBar.spec.tsx
📚 Learning: 2025-11-25T01:23:08.250Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.250Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : Mock `getBoundingClientRect` in tests using the helper function provided in `test/helper/MockGetBoundingClientRect.ts`

Applied to files:

  • test/tsconfig.json
  • test/cartesian/Area.spec.tsx
📚 Learning: 2025-12-14T13:58:58.361Z
Learnt from: PavelVanecek
Repo: recharts/recharts PR: 6771
File: src/shape/Curve.tsx:39-40
Timestamp: 2025-12-14T13:58:58.361Z
Learning: In the recharts codebase, `useAppSelector` and hooks like `useChartLayout()` are designed to return `undefined` when used outside Redux Provider context, rather than throwing errors. This allows components like `Curve` that call these hooks to work standalone by falling back to prop values.

Applied to files:

  • test/cartesian/XAxis/XAxis.vertical.spec.tsx
  • test/helper/createSelectorTestCase.tsx
📚 Learning: 2025-11-25T01:22:59.729Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-25T01:22:59.729Z
Learning: Applies to storybook/stories/**/*.stories.tsx : Use Storybook for smoke tests and add play functions with assertions for actual tests

Applied to files:

  • test/cartesian/XAxis/XAxis.vertical.spec.tsx
  • test/cartesian/ErrorBar.spec.tsx
  • storybook/tsconfig.json
📚 Learning: 2025-11-25T01:23:08.250Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.250Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : Use `userEvent.setup({ advanceTimers: vi.runOnlyPendingTimers })` or the `userEventSetup` helper function from `test/helper/userEventSetup.ts` when creating userEvent instances

Applied to files:

  • test/cartesian/ErrorBar.spec.tsx
📚 Learning: 2025-12-25T23:55:37.579Z
Learnt from: PavelVanecek
Repo: recharts/recharts PR: 6824
File: package.json:0-0
Timestamp: 2025-12-25T23:55:37.579Z
Learning: In the recharts repository, the `engines` field in package.json specifies requirements for library consumers and should only be changed with major version releases to avoid breaking changes. For development environment Node version requirements, use the `.nvmrc` file instead, which standardizes the development environment without impacting library consumers.

Applied to files:

  • src/chart/RechartsWrapper.tsx
📚 Learning: 2025-11-25T01:22:59.729Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-25T01:22:59.729Z
Learning: Applies to storybook/stories/**/*.stories.tsx : Update Storybook stories when APIs have been changed to ensure they work as expected

Applied to files:

  • storybook/tsconfig.json
📚 Learning: 2025-12-26T15:59:11.254Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: DEVELOPING.md:0-0
Timestamp: 2025-12-26T15:59:11.254Z
Learning: Applies to **/*.stories.{ts,tsx} : When adding new Storybook stories, prioritize high-fidelity examples that you want published on the website and in the Storybook UI. Use low-fidelity tests in unit tests or visual regression tests instead to avoid exceeding the Chromatic open source plan limits.

Applied to files:

  • storybook/tsconfig.json
🧬 Code graph analysis (20)
src/polar/PolarRadiusAxis.tsx (1)
src/util/types.ts (1)
  • TickItem (980-992)
src/component/LabelList.tsx (3)
src/util/types.ts (1)
  • DataKey (90-90)
src/index.ts (1)
  • DataKey (121-121)
src/util/ChartUtils.ts (1)
  • getValueByDataKey (44-62)
src/chart/SunburstChart.tsx (1)
src/state/tooltipSlice.ts (2)
  • TooltipPayloadSearcher (46-51)
  • TooltipIndex (39-39)
test/cartesian/Funnel.spec.tsx (2)
src/cartesian/Funnel.tsx (1)
  • FunnelTrapezoidItem (52-62)
src/index.ts (1)
  • FunnelTrapezoidItem (115-115)
test/state/selectors/selectors.spec.tsx (1)
src/chart/types.ts (1)
  • TooltipTrigger (4-4)
src/cartesian/Funnel.tsx (3)
src/util/ChartUtils.ts (1)
  • getValueByDataKey (44-62)
storybook/stories/API/props/CartesianComponentShared.ts (1)
  • dataKey (3-10)
src/index.ts (1)
  • FunnelTrapezoidItem (115-115)
src/chart/Sankey.tsx (2)
src/state/tooltipSlice.ts (2)
  • TooltipPayloadSearcher (46-51)
  • TooltipIndex (39-39)
src/index.ts (1)
  • TooltipIndex (17-17)
test/cartesian/XAxis/XAxis.vertical.spec.tsx (2)
src/cartesian/XAxis.tsx (1)
  • XAxis (299-299)
test/helper/expectAxisTicks.ts (2)
  • ExpectAxisDomain (39-51)
  • expectXAxisTicks (17-26)
src/cartesian/getTicks.ts (2)
src/util/TickUtils.ts (1)
  • isVisible (26-42)
src/util/DataUtils.ts (1)
  • mathSign (5-14)
src/state/optionsSlice.ts (2)
src/state/tooltipSlice.ts (2)
  • TooltipPayloadSearcher (46-51)
  • TooltipIndex (39-39)
src/util/DataUtils.ts (1)
  • isNan (16-19)
src/polar/Pie.tsx (1)
src/index.ts (1)
  • PieSectorDataItem (61-61)
src/shape/Curve.tsx (3)
storybook/stories/API/props/CartesianComponentShared.ts (1)
  • layout (67-75)
src/util/types.ts (3)
  • LayoutType (57-57)
  • Coordinate (125-128)
  • NullableCoordinate (130-133)
src/util/DataUtils.ts (1)
  • upperFirst (189-195)
test/helper/createSelectorTestCase.tsx (1)
src/state/store.ts (1)
  • RechartsRootState (23-38)
test/cartesian/Area.spec.tsx (1)
src/component/Label.tsx (1)
  • Label (621-712)
src/util/scale/RechartsScale.ts (4)
src/util/scale/CustomScaleDefinition.ts (1)
  • CustomScaleDefinition (13-71)
src/index.ts (1)
  • CustomScaleDefinition (97-97)
src/util/types.ts (1)
  • CategoricalDomainItem (757-757)
src/state/selectors/axisSelectors.ts (1)
  • AxisRange (1402-1402)
src/chart/RechartsWrapper.tsx (1)
src/context/chartLayoutContext.tsx (1)
  • ReportChartSize (178-221)
test/cartesian/Bar.spec.tsx (2)
src/cartesian/Bar.tsx (1)
  • Bar (1111-1111)
src/index.ts (1)
  • Bar (85-85)
test/helper/toBeRechartsScale.ts (1)
test/helper/expectScale.ts (1)
  • ExpectedScale (7-7)
src/chart/Treemap.tsx (2)
src/state/tooltipSlice.ts (2)
  • TooltipPayloadSearcher (46-51)
  • TooltipIndex (39-39)
src/util/DataUtils.ts (1)
  • isNan (16-19)
src/util/ChartUtils.ts (1)
src/util/types.ts (1)
  • DataKey (90-90)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Build, Test, Pack
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (65)
test/state/selectors/selectors.spec.tsx (1)

744-744: LGTM! Explicit generic typing improves type safety.

Adding the <TooltipTrigger> generic parameter provides better type inference for the test callback parameter and aligns with the PR's goal of enabling strict TypeScript checking.

src/component/ResponsiveContainer.tsx (1)

175-179: LGTM! Clean defensive pattern for strict TypeScript.

The null check for entries[0] properly handles TypeScript's strict indexed access (noUncheckedIndexedAccess), where array access returns T | undefined. While the ResizeObserver spec guarantees a non-empty array, this guard satisfies the compiler and adds runtime safety without affecting normal operation.

test/helper/expectStackGroups.ts (1)

71-71: Approve the error type guard pattern.

The change from directly accessing e.message to using e instanceof Error ? e.message : String(e) is the correct approach for TypeScript strict mode, where caught values are typed as unknown. This properly handles both Error objects and other thrown values.

Also applies to: 91-91, 114-114

src/component/Text.tsx (1)

430-432: LGTM! Appropriate null-safety guard for strict TypeScript.

The extraction of firstLine and the explicit null check align well with the strict TypeScript configuration. While the length check at line 406 logically guarantees that wordsByLines[0] exists, this defensive approach correctly handles the noUncheckedIndexedAccess compiler option, which types array access as potentially undefined. The downstream isNumber validation at line 434 provides an additional safety net for the width property.

src/chart/RechartsWrapper.tsx (3)

108-112: LGTM! Defensive guard for strict TypeScript.

The null check for entries[0] is appropriate for strict TypeScript mode and defensive programming, even though the ResizeObserver spec guarantees at least one entry in the callback.


187-187: LGTM! Improved type precision.

Refining the forwardRef signature to use StaticDivProps correctly enforces that StaticDiv only accepts numeric width and height values.


219-219: LGTM! Cleaner boolean check.

Simplifying to responsive ? ResponsiveDiv : NonResponsiveDiv is more idiomatic since responsive is already a boolean.

src/cartesian/getEquidistantTicks.ts (2)

94-96: LGTM! Appropriate null-safety guard.

The null check prevents potential runtime errors when iterating over ticks that may contain null or undefined entries. Using == null is idiomatic for checking both null and undefined in one condition.


132-135: LGTM! Consistent null-safety in result construction.

The null check when building the final ticks array ensures only valid tick entries are returned, maintaining consistency with the earlier null check at lines 94-96.

test/cartesian/ErrorBar.spec.tsx (1)

1263-1265: LGTM! Appropriate use of as const for test data.

The change correctly uses as const (the only permitted type assertion per coding guidelines) to create a readonly tuple with literal types, and removes the explicit parameter type annotation to rely on inference. This simplifies the test while maintaining type safety.

Based on learnings, as const is the only permitted type assertion in TypeScript.

test/polar/PolarGrid.spec.tsx (3)

36-38: LGTM! Improved type safety with explicit SVG element types.

Adding the <SVGLineElement> type parameter to querySelectorAll provides better type inference, eliminating the need for explicit parameter type annotations in the map callback while maintaining type safety.


56-59: LGTM! Consistent type-safe pattern for SVG polygons.

The explicit <SVGPathElement> type parameter provides proper type inference while the inline return type annotation maintains clarity about the return value structure.


77-80: LGTM! Consistent type-safe pattern for SVG circles.

The explicit <SVGCircleElement> type parameter completes the consistent pattern of type-safe SVG element handling across all three helper functions in this file.

test/chart/LineChart.spec.tsx (1)

494-494: LGTM! Appropriate type broadening for test helper.

Making the properties optional and allowing string | number for coordinates provides flexibility for various test scenarios while maintaining type safety. This aligns with similar test typing improvements across the codebase.

tsconfig.base.json (1)

1-21: LGTM! Comprehensive strict TypeScript configuration.

This base configuration appropriately enables all strict type-checking options, which directly supports the PR objectives of fixing TypeScript problems and enforcing stricter compilation rules. Key highlights:

  • strictNullChecks: true - requires the null checks being added throughout the codebase
  • noUncheckedIndexedAccess: true - enforces safe array/object property access
  • noImplicitAny: true - aligns with coding guidelines to never use implicit any
  • useUnknownInCatchVariables: true - enforces using unknown over any in catch blocks

These settings provide the foundation for the type safety improvements throughout this PR.

Based on learnings and coding guidelines, these strict settings enforce never using any type and requiring explicit types.

src/cartesian/getTicks.ts (1)

25-33: LGTM! Excellent null-safety improvements.

The null-safety guards are well-implemented:

  • The initialEntry pattern correctly skips null array elements and preserves the original entry for size calculations
  • The tail processing is properly guarded with if (tail != null)
  • Sign computation safely defaults to 1 when insufficient ticks are available

These changes strengthen the robustness of tick generation without altering the core logic.

Also applies to: 79-95, 100-108, 178-180

test/helper/createSelectorTestCase.tsx (1)

12-12: LGTM! Type simplifications improve test helper flexibility.

The changes correctly loosen the type constraints:

  • emptySelector no longer requires the Redux Toolkit Selector type wrapper
  • Parameter types in isReactHook and getComp now accept plain state-to-value functions

These adjustments align well with the stricter TypeScript configuration while maintaining type safety in test utilities.

Also applies to: 38-43

test/cartesian/YAxis/YAxis.spec.tsx (1)

1229-1229: LGTM! Correct use of as const for tuple type inference.

The as const assertion appropriately narrows the array to a readonly tuple type, enabling better type inference for the it.each() test parameters. This aligns with the coding guideline that permits as const as the only allowed type assertion.

src/util/ChartUtils.ts (1)

44-62: LGTM! Signature change safely accommodates nullish inputs.

The updated signature obj: T | null | undefined correctly reflects that the function can handle nullish objects. The existing isNullish(obj) guard on line 49 ensures safe handling.

This change strengthens type safety across all call sites and aligns with the PR's strict null-checking improvements.

tsconfig.json (1)

17-17: LGTM! Strict TypeScript mode successfully enabled.

These configuration changes are the culmination of the PR's objective:

  • strictFunctionTypes: true enforces stricter function type checking (contravariant parameters)
  • noUncheckedIndexedAccess: true makes indexed access return T | undefined, preventing unsafe array/object access

The TODOs referencing issue #6645 are now resolved. The codebase-wide null-safety guards and type refinements throughout this PR ensure compatibility with these stricter compiler checks.

Also applies to: 23-23

test/cartesian/Scatter.spec.tsx (1)

116-118: LGTM!

The optional typing for cx and cy aligns with the stricter TypeScript configuration. SVG attributes handle undefined gracefully, so this is a safe type relaxation for test compatibility.

test/helper/toBeRechartsScale.ts (1)

6-22: LGTM!

The changes improve type safety and correctness:

  1. Explicit return type aligns with Vitest's custom matcher contract.
  2. The instanceof Error check handles edge cases where non-Error values are thrown.
  3. Wrapping errorMessage in a function ensures consistent return structure.
src/polar/Pie.tsx (1)

877-878: LGTM!

The explicit typing and nullish coalescing provide proper null-safety when sectors is empty or startAngle is undefined. This defensive approach aligns with the PR's goal of stricter TypeScript handling.

src/component/Tooltip.tsx (1)

38-40: LGTM!

Using concrete ValueType and NameType instead of generics for the internal defaultUniqBy function is appropriate since it's only used as a fallback within the Tooltip component.

src/polar/PolarRadiusAxis.tsx (1)

267-272: LGTM!

The explicit type annotations for the reduce operation improve type safety and clarity. The tuple typing [number, number] correctly represents the extent calculation.

test/cartesian/Bar.spec.tsx (1)

1263-1267: LGTM!

The test correctly reflects the widened minPointSize callback signature. The null guard value != null && value > 0 properly handles the new nullable parameter type.

test/tsconfig.json (1)

2-9: LGTM!

Extending from tsconfig.base.json ensures consistent TypeScript settings across the project. Disabling noUncheckedIndexedAccess specifically for tests is a pragmatic tradeoff, and the comment documents the reasoning well.

storybook/tsconfig.json (2)

2-2: LGTM – Consolidates TypeScript configuration.

Extending from a shared base config promotes consistency across the project.


8-9: Technical debt acknowledged.

The comment explicitly documents why noUncheckedIndexedAccess is disabled for Storybook. This is a pragmatic decision to scope the strictness effort, as the setting only affects Storybook stories and not production code or public API declarations.

src/chart/SunburstChart.tsx (1)

182-187: LGTM – Type signature generalized to match TooltipPayloadSearcher.

The signature now conforms to the broader TooltipPayloadSearcher type (from src/state/tooltipSlice.ts), accepting and returning unknown instead of specific types. The implementation correctly handles the activeIndex null check and delegates to es-toolkit/compat/get, which safely handles unknown data.

test/cartesian/Funnel.spec.tsx (2)

3-3: LGTM – Public API import follows guidelines.

Import from ../../src correctly uses the public API entry point.


77-88: LGTM – Type accuracy improved.

The activeShape callback now correctly receives FunnelTrapezoidItem instead of FunnelProps, accurately reflecting the runtime payload type. The properties accessed (x, y, height, upperWidth) align with the FunnelTrapezoidItem definition.

src/cartesian/ReferenceLine.tsx (1)

305-311: LGTM – Adds null-safety for strict TypeScript mode.

Explicit element access with null checks ensures type safety when noUncheckedIndexedAccess is enabled. The destructuring occurs after validation, preventing potential runtime errors.

test/cartesian/Area.spec.tsx (3)

53-61: LGTM – Test types loosened appropriately.

Making index, x, and y optional and widening x/y to string | number accommodates the flexible label API without changing test behavior.


73-81: LGTM – Consistent with label render function typing.

The Label component props mirror the loosened types from the render function, maintaining consistency across the test file.


89-89: LGTM – Props passed through correctly.

The inline function correctly forwards index, x, and y to the Label component.

src/cartesian/CartesianGrid.tsx (2)

332-334: Good null-safety improvement.

Using an explicit == null check instead of a falsy check (!array[i+1]) is safer here, as 0 is a valid coordinate value that would incorrectly be treated as falsy with the old approach.


370-372: Consistent with the HorizontalStripes fix.

Same null-safety improvement applied consistently to VerticalStripes.

src/cartesian/Line.tsx (1)

410-415: Solid null-safety guards in stroke dasharray calculation.

The changes properly guard against potentially undefined array elements:

  • Using lines[i] ?? 0 prevents NaN from propagating through the sum
  • The explicit lineValue != null check before comparison is safer than relying on implicit coercion
src/cartesian/Brush.tsx (4)

250-260: Appropriate null-safety in binary search.

Guarding middleValue and endValue against null prevents potential runtime errors when accessing array elements that might be undefined (e.g., out-of-bounds access).


643-646: Safer touch event handling.

Using optional chaining on changedTouches?.[0] and checking for null before calling handleDrag prevents potential errors when touch events don't have the expected structure.


698-700: Consistent early return pattern for null events.

Both handleSlideDragStart and handleTravellerDragStart now properly exit early if the computed event is null, preventing downstream errors when accessing event.pageX.

Also applies to: 745-747


836-838: Guard against invalid scale value.

The null check on newScaleValue prevents comparing undefined against endX/startX and setting invalid state.

src/cartesian/YAxis.tsx (2)

2-2: Import is correct.

The isValidElement is properly imported from React and used at line 237. The AI summary incorrectly stated it was removed.


209-291: Function declaration style change looks good.

Converting from an arrow function with explicit FunctionComponent<Props> type annotation to a regular function declaration is a valid refactor. The typing is preserved through the PropsWithDefaults parameter type.

test/cartesian/XAxis/XAxis.vertical.spec.tsx (2)

28-69: Good use of as const for type inference.

Using as const on the it.each array preserves the literal types ('category' | undefined), allowing TypeScript to properly infer the axisDomainType parameter type without needing an explicit AxisDomainTypeInput annotation. This is cleaner and more idiomatic.


71-73: Consistent typing pattern applied.

Same as const pattern applied consistently to the second test case.

src/component/LabelList.tsx (3)

25-25: Improved payload typing.

Changing from unknown to Record<string, unknown> | null | undefined is more specific and enables better type checking when accessing properties on the payload object.


80-80: Good change from any to unknown.

Changing DataKey<Record<string, any>> to DataKey<Record<string, unknown>> aligns with the coding guideline to never use any type and prefer unknown instead.


184-184: Safe guard removal.

Removing entry && from the getValueByDataKey call is safe because:

  1. entry is guaranteed to exist as we're iterating over the data array
  2. getValueByDataKey already handles null | undefined for its first argument (as shown in the relevant code snippet: if (isNullish(obj) || isNullish(dataKey)) { return defaultValue; })
src/state/cartesianAxisSlice.ts (1)

33-38: No action needed. The type change is correct.

BaseCartesianAxis.scale should not include undefined because this type represents user-provided Redux configuration that always requires a scale value. The undefined handling is properly isolated to computed types: RechartsScale | undefined values are produced by selectors, and functions like rechartsScaleFactory explicitly handle undefined cases through overloads. There is no evidence of BaseCartesianAxis.scale being set to undefined anywhere in the codebase, and selectors that use this type deliberately narrow the scale property to non-undefined RechartsScale through the BaseAxisWithScale type derivation.

src/state/optionsSlice.ts (1)

30-41: LGTM — Good defensive typing for strict mode compliance.

The refactoring from a generic function to a typed constant with unknown input properly aligns with the TooltipPayloadSearcher type signature. The Array.isArray(data) guard and isNan check provide appropriate runtime safety.

src/util/scale/RechartsScale.ts (1)

147-170: LGTM — Well-structured overloads for type narrowing.

The overloads provide proper type inference for callers, ensuring that passing undefined explicitly returns undefined, while passing a concrete scale type returns a concrete RechartsScale. This is a good pattern for strict TypeScript compliance.

src/chart/Sankey.tsx (1)

508-528: LGTM — Proper defensive guards for unknown data.

The runtime guards for computedData correctly check for null before the typeof check (since typeof null === 'object' in JavaScript). The signature change to unknown aligns with the stricter TooltipPayloadSearcher type.

src/cartesian/Funnel.tsx (2)

581-585: LGTM — Safe numeric extraction with fallback.

Good defensive pattern: mapping values through getValueByDataKey and ensuring numeric output with a fallback to 0 for non-numeric values.


656-656: LGTM — Safe object spread with type guard.

The guard entry != null && typeof entry === 'object' correctly prevents spreading primitives or null values, which would cause runtime errors.

src/chart/Treemap.tsx (6)

72-72: LGTM — Strict index signature.

Changing from any to unknown enforces proper type checking when accessing arbitrary properties on TreemapNode, aligning with strict TypeScript guidelines.


75-88: LGTM — Well-implemented type guard.

The isTreemapNode function properly validates both the presence and types of required properties. The pattern of checking 'x' in value before casting is safe and idiomatic.


90-95: LGTM — Generalized payload searcher.

The signature change to unknown input/output aligns with TooltipPayloadSearcher and requires callers to validate the result (e.g., via isTreemapNode).


146-151: LGTM — Safe value extraction with fallback.

Using child.value directly (line 146) is cleaner than index access, and the leaf value extraction (lines 149-151) properly handles non-numeric values with a fallback to 0.


876-877: LGTM — Defensive name extraction.

Good pattern: extracting the raw value and validating it's a string before use, with a sensible fallback to 'root'.


923-923: LGTM — Proper use of type guard.

Using isTreemapNode(activeNode) before accessing properties ensures type safety after the treemapPayloadSearcher returns unknown.

src/shape/Curve.tsx (3)

23-24: LGTM!

Good aliasing choice to avoid confusion with recharts' own Area and Line components while maintaining clear D3-prefixed naming.


91-105: LGTM!

The explicit return type annotation and the null guard for the factory lookup improve type safety. The fallback logic correctly defers to the generic lookup at line 104 if the specialized monotone/bump factory isn't found.


217-245: LGTM!

The @ts-expect-error directive is well-documented with a thorough explanation of why d3's type definitions don't support this pattern. The approach is honest about the type limitation while maintaining runtime correctness—defined() filters nullable points before getX/getY are called.

*/
offset?: number;
payloadUniqBy?: UniqueOption<Payload<TValue, TName>>;
payloadUniqBy?: UniqueOption<TooltipPayloadEntry>;
Copy link
Contributor

@coderabbitai coderabbitai bot Jan 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# First, let's see the context of the Tooltip.tsx file around line 126
fd -t f 'Tooltip.tsx' src/

Repository: recharts/recharts

Length of output: 86


🏁 Script executed:

# Search for payloadUniqBy usages to understand impact
rg -n -C2 'payloadUniqBy' --max-count=20

Repository: recharts/recharts

Length of output: 2627


🏁 Script executed:

# Check the definition and exports of TooltipPayloadEntry
rg -n 'TooltipPayloadEntry' --max-count=20

Repository: recharts/recharts

Length of output: 2373


🏁 Script executed:

# Check the public API exports from recharts
cat src/index.ts | head -100

Repository: recharts/recharts

Length of output: 5252


Export TooltipPayloadEntry from the public API entry point.

The payloadUniqBy prop type in TooltipProps uses TooltipPayloadEntry, but this type is not exported from src/index.ts. Consumers cannot properly type their payloadUniqBy function without importing from internal paths (src/state/tooltipSlice), which violates the linter rules requiring all imports to use the public API entry point. Add export type { TooltipPayloadEntry } from './state/tooltipSlice'; to src/index.ts.

🤖 Prompt for AI Agents
In src/component/Tooltip.tsx around line 126, the TooltipProps uses
TooltipPayloadEntry but that type is not exported from the package public API;
update src/index.ts to re-export the type TooltipPayloadEntry from the internal
state/tooltipSlice module so consumers can import it from the public entry point
(i.e., add a type re-export in src/index.ts that forwards TooltipPayloadEntry
from ./state/tooltipSlice).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

technically true, though its the same type as before

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check what's exported from src/index.ts related to Payload and TooltipPayloadEntry
echo "=== Checking exports from src/index.ts ==="
rg -n "Payload|TooltipPayloadEntry" src/index.ts

echo -e "\n=== Checking Payload type in DefaultTooltipContent ==="
rg -n "^export.*Payload" src/component/DefaultTooltipContent.tsx

echo -e "\n=== Checking TooltipPayloadEntry definition ==="
rg -n "^export.*TooltipPayloadEntry" src/state/tooltipSlice.ts

Length of output: 604


@ckifer, you're absolutely right that TooltipPayloadEntry is just an alias for Payload<ValueType, NameType>, so structurally it's the same type. And you're also correct that this issue existed before—Payload wasn't exported from the public API either, so consumers couldn't properly type their payloadUniqBy functions before this PR.

Since you're already making the type more explicit in the signature, this would be a good opportunity to export TooltipPayloadEntry from src/index.ts so consumers can finally type their custom uniqueness functions properly. But I understand if you'd prefer to address that in a follow-up rather than expanding the scope of this PR.

Thanks for the context! 🙂


🧬 Code Graph Analysis Results

[src/state/tooltipSlice.ts] lines 39-39

export type TooltipIndex = string | null;

[src/state/tooltipSlice.ts] lines 12-12

export type TooltipPayloadEntry = Payload<ValueType, NameType>;

[src/state/tooltipSlice.ts] lines 30-30

export type TooltipPayload = ReadonlyArray<TooltipPayloadEntry>;

[src/util/payload/getUniqPayload.ts] lines 12-12

export type UniqueOption<T> = boolean | UniqueFunc<T>;

[src/util/payload/getUniqPayload.ts] lines 14-28

export function getUniqPayload<T>(
  payload: ReadonlyArray<T>,
  option: UniqueOption<T> | undefined,
  defaultUniqBy: UniqueFunc<T>,
): ReadonlyArray<T> {
  if (option === true) {
    return uniqBy(payload, defaultUniqBy);
  }

  if (typeof option === 'function') {
    return uniqBy(payload, option);
  }

  return payload;
}

[src/util/types.ts] lines 125-128

export interface Coordinate {
  x: number;
  y: number;
}

[src/util/types.ts] lines 120-123

export type AllowInDimension = {
  x?: boolean;
  y?: boolean;
};

[src/state/selectors/selectors.ts] lines 188-198

export const selectIsTooltipActive: (
  state: RechartsRootState,
  tooltipEventType: TooltipEventType | undefined,
  trigger: TooltipTrigger,
  defaultIndex: TooltipIndex | undefined,
) => { isActive: boolean; activeIndex: TooltipIndex | null } = createSelector(
  [selectTooltipInteractionState, selectActiveIndex],
  (tooltipInteractionState: TooltipInteractionState, activeIndex: TooltipIndex | null) => {
    return { isActive: tooltipInteractionState.active && activeIndex != null, activeIndex };
  },
);

[src/state/selectors/selectors.ts] lines 163-168

export const selectActiveLabel: (
  state: RechartsRootState,
  tooltipEventType: TooltipEventType | undefined,
  trigger: TooltipTrigger,
  defaultIndex: TooltipIndex | undefined,
) => string | number | undefined = createSelector([selectTooltipAxisTicks, selectActiveIndex], combineActiveLabel);

[src/state/selectors/selectors.ts] lines 147-161

export const selectActiveCoordinate: (
  state: RechartsRootState,
  tooltipEventType: TooltipEventType | undefined,
  trigger: TooltipTrigger,
  defaultIndex: TooltipIndex | undefined,
  // TODO the state is marked as containing Coordinate but actually in polar charts it contains PolarCoordinate, we should keep the polar state separate
) => Coordinate | PolarCoordinate | undefined = createSelector(
  [selectTooltipInteractionState, selectCoordinateForDefaultIndex],
  (
    tooltipInteractionState: TooltipInteractionState,
    defaultIndexCoordinate: Coordinate | undefined,
  ): Coordinate | PolarCoordinate | undefined => {
    return tooltipInteractionState.coordinate ?? defaultIndexCoordinate;
  },
);

[src/state/selectors/selectors.ts] lines 170-186

export const selectTooltipPayload: (
  state: RechartsRootState,
  tooltipEventType: TooltipEventType | undefined,
  trigger: TooltipTrigger,
  defaultIndex: TooltipIndex | undefined,
) => TooltipPayload | undefined = createSelector(
  [
    selectTooltipPayloadConfigurations,
    selectActiveIndex,
    selectChartDataWithIndexes,
    selectTooltipAxisDataKey,
    selectActiveLabel,
    selectTooltipPayloadSearcher,
    pickTooltipEventType,
  ],
  combineTooltipPayload,
);

[src/context/tooltipPortalContext.tsx] lines 5-5

export const useTooltipPortal = (): HTMLElement | null => useContext(TooltipPortalContext);

[src/context/accessibilityContext.tsx] lines 3-4

export const useAccessibilityLayer: () => boolean = () =>
  useAppSelector(state => state.rootProps.accessibilityLayer) ?? true;

[src/state/selectors/selectTooltipEventType.ts] lines 33-35

export function useTooltipEventType(shared: SharedTooltipSettings): TooltipEventType | undefined {
  return useAppSelector(state => selectTooltipEventType(state, shared));
}

[src/component/DefaultTooltipContent.tsx] lines 18-18

export type NameType = number | string;

[src/component/DefaultTooltipContent.tsx] lines 17-17

export type ValueType = number | string | ReadonlyArray<number | string>;

[src/component/DefaultTooltipContent.tsx] lines 27-48

export interface Payload<TValue extends ValueType, TName extends NameType> extends Omit<SVGProps<SVGElement>, 'name'> {
  type?: TooltipType;
  color?: string;
  formatter?: Formatter<TValue, TName>;
  name?: TName;
  value?: TValue;
  unit?: ReactNode;
  fill?: string;
  dataKey?: DataKey<any>;
  nameKey?: DataKey<any>;
  payload?: any;
  chartType?: string;
  stroke?: string;
  strokeDasharray?: string | number;
  strokeWidth?: number | string;
  className?: string;
  hide?: boolean;
  /**
   * The id of the graphical item that the data point belongs to
   */
  graphicalItemId: string;
}

[src/component/DefaultTooltipContent.tsx] lines 65-173

export const DefaultTooltipContent = <TValue extends ValueType, TName extends NameType>(
  props: Props<TValue, TName>,
) => {
  const {
    separator = ' : ',
    contentStyle = {},
    itemStyle = {},
    labelStyle = {},
    payload,
    formatter,
    itemSorter,
    wrapperClassName,
    labelClassName,
    label,
    labelFormatter,
    accessibilityLayer = false,
  } = props;

  const renderContent = () => {
    if (payload && payload.length) {
      const listStyle = { padding: 0, margin: 0 };

      const items = (itemSorter ? sortBy(payload, itemSorter) : payload).map(
        (entry: Payload<TValue, TName>, i: number) => {
          if (entry.type === 'none') {
            return null;
          }

          const finalFormatter: Formatter<TValue, TName> = entry.formatter || formatter || defaultFormatter;
          const { value, name } = entry;
          let finalValue: React.ReactNode = value;
          let finalName: React.ReactNode = name;
          if (finalFormatter) {
            const formatted = finalFormatter(value, name, entry, i, payload);
            if (Array.isArray(formatted)) {
              [finalValue, finalName] = formatted;
            } else if (formatted != null) {
              finalValue = formatted;
            } else {
              return null;
            }
          }

          const finalItemStyle = {
            display: 'block',
            paddingTop: 4,
            paddingBottom: 4,
            color: entry.color || '#000',
            ...itemStyle,
          };

          return (
            <li className="recharts-tooltip-item" key={`tooltip-item-${i}`} style={finalItemStyle}>
              {isNumOrStr(finalName) ? <span className="recharts-tooltip-item-name">{finalName}</span> : null}
              {isNumOrStr(finalName) ? <span className="recharts-tooltip-item-separator">{separator}</span> : null}
              <span className="recharts-tooltip-item-value">{finalValue}</span>
              <span className="recharts-tooltip-item-unit">{entry.unit || ''}</span>
            </li>
          );
        },
      );

      return (
        <ul className="recharts-tooltip-item-list" style={listStyle}>
          {items}
        </ul>
      );
    }

    return null;
  };

  const finalStyle: React.CSSProperties = {
    margin: 0,
    padding: 10,
    backgroundColor: '#fff',
    border: '1px solid #ccc',
    whiteSpace: 'nowrap',
    ...contentStyle,
  };
  const finalLabelStyle = {
    margin: 0,
    ...labelStyle,
  };
  const hasLabel = !isNullish(label);
  let finalLabel = hasLabel ? label : '';
  const wrapperCN = clsx('recharts-default-tooltip', wrapperClassName);
  const labelCN = clsx('recharts-tooltip-label', labelClassName);

  if (hasLabel && labelFormatter && payload !== undefined && payload !== null) {
    finalLabel = labelFormatter(label, payload);
  }

  const accessibilityAttributes = accessibilityLayer
    ? ({
        role: 'status',
        'aria-live': 'assertive',
      } as HTMLAttributes<HTMLDivElement>)
    : {};

  return (
    <div className={wrapperCN} style={finalStyle} {...accessibilityAttributes}>
      <p className={labelCN} style={finalLabelStyle}>
        {React.isValidElement(finalLabel) ? finalLabel : `${finalLabel}`}
      </p>
      {renderContent()}
    </div>
  );
};

🧠 Learnings used
Learnt from: PavelVanecek
Repo: recharts/recharts PR: 6669
File: www/src/docs/exampleComponents/ScatterChart/ScatterChartWithLabels.tsx:2-2
Timestamp: 2025-11-23T13:30:10.395Z
Learning: The `TooltipIndex` type from recharts is defined in `src/state/tooltipSlice.ts` but is not currently exported from the public API entry points. It should not be imported from `recharts/types/state/tooltipSlice` as this is an internal implementation path. An ESLint rule is needed to prevent regressions.

Learnt from: CR
Repo: recharts/recharts PR: 0
File: DEVELOPING.md:0-0
Timestamp: 2025-12-26T15:59:11.254Z
Learning: Applies to **/*.{ts,tsx} : All imports from `recharts` must use the public API entry point (e.g., `import { TooltipIndex } from 'recharts'`). Imports from internal paths like `recharts/types/*` or `recharts/src/*` are not allowed and will fail the linter.

Learnt from: PavelVanecek
Repo: recharts/recharts PR: 6783
File: test/util/ChartUtils.spec.tsx:15-16
Timestamp: 2025-12-16T08:12:13.355Z
Learning: In the recharts codebase, files in the `test` folder are allowed to import from internal paths (e.g., `../../src/state/cartesianAxisSlice`) and do not need to use the public API entry point (`src/index.ts`). The public API import restriction applies only to non-test code.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/chart/Treemap.tsx (1)

76-89: Consider expanding type guard to check additional required fields.

The current guard validates only geometric properties (x, y, width, height). For more robust runtime validation, consider checking additional required fields like name, tooltipIndex, and value to ensure the object truly conforms to the TreemapNode interface.

🔎 Enhanced type guard
 function isTreemapNode(value: unknown): value is TreemapNode {
   return (
     value != null &&
     typeof value === 'object' &&
     'x' in value &&
     'y' in value &&
     'width' in value &&
     'height' in value &&
     typeof (value as TreemapNode).x === 'number' &&
     typeof (value as TreemapNode).y === 'number' &&
     typeof (value as TreemapNode).width === 'number' &&
-    typeof (value as TreemapNode).height === 'number'
+    typeof (value as TreemapNode).height === 'number' &&
+    'name' in value &&
+    'tooltipIndex' in value &&
+    'value' in value &&
+    typeof (value as TreemapNode).value === 'number'
   );
 }
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7ea742c and d5e4eba.

📒 Files selected for processing (12)
  • src/chart/Treemap.tsx
  • src/component/LabelList.tsx
  • src/index.ts
  • src/shape/Curve.tsx
  • storybook/stories/API/chart/RadialBarChart.stories.tsx
  • storybook/stories/API/chart/Treemap.stories.tsx
  • storybook/stories/Examples/cartesian/Area/AreaWithCustomLabel.stories.tsx
  • test/chart/LineChart.spec.tsx
  • test/helper/expectStackGroups.ts
  • tsconfig.json
  • www/src/components/GuideView/ZIndex/PrahaMetro.tsx
  • www/src/docs/exampleComponents/TreeMap/CustomContentTreemap.tsx
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

**/*.{ts,tsx}: Never use any type (implicit or explicit) in TypeScript code
Prefer unknown over any and refine the type in TypeScript
Type function parameters and return values explicitly in TypeScript, do not rely on implicit any or inference; exceptions are React components and trivial functions
Do not use as type assertions in TypeScript; the only exception is as const

All imports from recharts must use the public API entry point (e.g., import { TooltipIndex } from 'recharts'). Imports from internal paths like recharts/types/* or recharts/src/* are not allowed and will fail the linter.

Files:

  • www/src/docs/exampleComponents/TreeMap/CustomContentTreemap.tsx
  • test/helper/expectStackGroups.ts
  • storybook/stories/API/chart/Treemap.stories.tsx
  • test/chart/LineChart.spec.tsx
  • src/chart/Treemap.tsx
  • www/src/components/GuideView/ZIndex/PrahaMetro.tsx
  • src/shape/Curve.tsx
  • src/component/LabelList.tsx
  • src/index.ts
  • storybook/stories/Examples/cartesian/Area/AreaWithCustomLabel.stories.tsx
  • storybook/stories/API/chart/RadialBarChart.stories.tsx
**/*.{js,ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Ensure code lints by running npm run lint and follows Airbnb's Style Guide

Files:

  • www/src/docs/exampleComponents/TreeMap/CustomContentTreemap.tsx
  • test/helper/expectStackGroups.ts
  • storybook/stories/API/chart/Treemap.stories.tsx
  • test/chart/LineChart.spec.tsx
  • src/chart/Treemap.tsx
  • www/src/components/GuideView/ZIndex/PrahaMetro.tsx
  • src/shape/Curve.tsx
  • src/component/LabelList.tsx
  • src/index.ts
  • storybook/stories/Examples/cartesian/Area/AreaWithCustomLabel.stories.tsx
  • storybook/stories/API/chart/RadialBarChart.stories.tsx
storybook/stories/**/*.stories.tsx

📄 CodeRabbit inference engine (CONTRIBUTING.md)

storybook/stories/**/*.stories.tsx: Use Storybook for smoke tests and add play functions with assertions for actual tests
Update Storybook stories when APIs have been changed to ensure they work as expected

Files:

  • storybook/stories/API/chart/Treemap.stories.tsx
  • storybook/stories/Examples/cartesian/Area/AreaWithCustomLabel.stories.tsx
  • storybook/stories/API/chart/RadialBarChart.stories.tsx
**/*.stories.{ts,tsx}

📄 CodeRabbit inference engine (DEVELOPING.md)

When adding new Storybook stories, prioritize high-fidelity examples that you want published on the website and in the Storybook UI. Use low-fidelity tests in unit tests or visual regression tests instead to avoid exceeding the Chromatic open source plan limits.

Files:

  • storybook/stories/API/chart/Treemap.stories.tsx
  • storybook/stories/Examples/cartesian/Area/AreaWithCustomLabel.stories.tsx
  • storybook/stories/API/chart/RadialBarChart.stories.tsx
test/**/*.spec.{ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Aim for 100% unit test code coverage when writing new code

Files:

  • test/chart/LineChart.spec.tsx
test/**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (test/README.md)

test/**/*.{test,spec}.{ts,tsx}: Aim for 100% unit test code coverage when writing new code
Prefer to use the createSelectorTestCase helper function when writing or modifying tests
Use the expectLastCalledWith helper function instead of expect(spy).toHaveBeenLastCalledWith(...) for better typing and autocompletion
Verify the number of selector calls using the spy object from createSelectorTestCase to spot unnecessary re-renders and improve performance
Mock getBoundingClientRect in tests using the helper function provided in test/helper/MockGetBoundingClientRect.ts
Use vi.useFakeTimers() in all tests due to Redux autoBatchEnhancer dependency on timers and requestAnimationFrame
Call vi.runOnlyPendingTimers() to advance timers after renders when not using createSelectorTestCase helper, and avoid vi.runAllTimers() to prevent infinite loops
Use userEvent.setup({ advanceTimers: vi.runOnlyPendingTimers }) or the userEventSetup helper function from test/helper/userEventSetup.ts when creating userEvent instances
When testing tooltips on hover, use vi.runOnlyPendingTimers() after each userEvent.hover() call or use the showTooltip helper function from tooltipTestHelpers.ts to account for requestAnimationFrame delays

Files:

  • test/chart/LineChart.spec.tsx
**/*.spec.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

When running unit tests, prefer to run a single test file using npm run test -- path/to/TestFile.spec.tsx rather than running all tests with npm test

Unit tests should be placed in the test directory, with some tests also allowed in www/test. Test files follow the naming convention *.spec.tsx.

Files:

  • test/chart/LineChart.spec.tsx
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Do not hardcode any strings or formatting choices in library code; users should provide localized strings as desired

Files:

  • src/chart/Treemap.tsx
  • src/shape/Curve.tsx
  • src/component/LabelList.tsx
  • src/index.ts
🧠 Learnings (22)
📓 Common learnings
Learnt from: CR
Repo: recharts/recharts PR: 0
File: DEVELOPING.md:0-0
Timestamp: 2025-12-26T15:59:11.254Z
Learning: Applies to **/*.{ts,tsx} : All imports from `recharts` must use the public API entry point (e.g., `import { TooltipIndex } from 'recharts'`). Imports from internal paths like `recharts/types/*` or `recharts/src/*` are not allowed and will fail the linter.
Learnt from: CR
Repo: recharts/recharts PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-25T01:22:59.729Z
Learning: Applies to **/*.{ts,tsx} : Prefer `unknown` over `any` and refine the type in TypeScript
Learnt from: CR
Repo: recharts/recharts PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-25T01:22:59.729Z
Learning: Applies to **/*.{ts,tsx} : Type function parameters and return values explicitly in TypeScript, do not rely on implicit any or inference; exceptions are React components and trivial functions
Learnt from: CR
Repo: recharts/recharts PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-25T01:22:59.729Z
Learning: Applies to storybook/stories/**/*.stories.tsx : Update Storybook stories when APIs have been changed to ensure they work as expected
Learnt from: CR
Repo: recharts/recharts PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-25T01:22:59.729Z
Learning: Applies to **/*.{ts,tsx} : Never use `any` type (implicit or explicit) in TypeScript code
Learnt from: CR
Repo: recharts/recharts PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-25T01:22:59.729Z
Learning: Applies to **/*.{ts,tsx} : Do not use `as` type assertions in TypeScript; the only exception is `as const`
Learnt from: CR
Repo: recharts/recharts PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T01:23:14.977Z
Learning: Applies to src/**/*.{ts,tsx} : Do not hardcode any strings or formatting choices in library code; users should provide localized strings as desired
Learnt from: CR
Repo: recharts/recharts PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-25T01:22:59.729Z
Learning: Applies to **/*.{js,ts,tsx} : Ensure code lints by running `npm run lint` and follows Airbnb's Style Guide
📚 Learning: 2025-11-25T01:22:59.729Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-25T01:22:59.729Z
Learning: Applies to **/*.{ts,tsx} : Do not use `as` type assertions in TypeScript; the only exception is `as const`

Applied to files:

  • tsconfig.json
📚 Learning: 2025-11-25T01:22:59.729Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-25T01:22:59.729Z
Learning: Applies to **/*.{ts,tsx} : Prefer `unknown` over `any` and refine the type in TypeScript

Applied to files:

  • tsconfig.json
📚 Learning: 2025-12-26T15:59:11.254Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: DEVELOPING.md:0-0
Timestamp: 2025-12-26T15:59:11.254Z
Learning: Applies to **/*.{ts,tsx} : All imports from `recharts` must use the public API entry point (e.g., `import { TooltipIndex } from 'recharts'`). Imports from internal paths like `recharts/types/*` or `recharts/src/*` are not allowed and will fail the linter.

Applied to files:

  • tsconfig.json
  • storybook/stories/API/chart/Treemap.stories.tsx
  • test/chart/LineChart.spec.tsx
  • src/chart/Treemap.tsx
  • www/src/components/GuideView/ZIndex/PrahaMetro.tsx
  • src/index.ts
  • storybook/stories/Examples/cartesian/Area/AreaWithCustomLabel.stories.tsx
  • storybook/stories/API/chart/RadialBarChart.stories.tsx
📚 Learning: 2025-12-16T08:12:13.355Z
Learnt from: PavelVanecek
Repo: recharts/recharts PR: 6783
File: test/util/ChartUtils.spec.tsx:15-16
Timestamp: 2025-12-16T08:12:13.355Z
Learning: In the recharts codebase, files in the `test` folder are allowed to import from internal paths (e.g., `../../src/state/cartesianAxisSlice`) and do not need to use the public API entry point (`src/index.ts`). The public API import restriction applies only to non-test code.

Applied to files:

  • tsconfig.json
  • test/helper/expectStackGroups.ts
  • storybook/stories/API/chart/Treemap.stories.tsx
  • www/src/components/GuideView/ZIndex/PrahaMetro.tsx
  • storybook/stories/Examples/cartesian/Area/AreaWithCustomLabel.stories.tsx
  • storybook/stories/API/chart/RadialBarChart.stories.tsx
📚 Learning: 2025-11-25T01:22:59.729Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-25T01:22:59.729Z
Learning: Applies to **/*.{ts,tsx} : Type function parameters and return values explicitly in TypeScript, do not rely on implicit any or inference; exceptions are React components and trivial functions

Applied to files:

  • tsconfig.json
📚 Learning: 2025-12-25T23:55:37.579Z
Learnt from: PavelVanecek
Repo: recharts/recharts PR: 6824
File: package.json:0-0
Timestamp: 2025-12-25T23:55:37.579Z
Learning: In the recharts repository, the `engines` field in package.json specifies requirements for library consumers and should only be changed with major version releases to avoid breaking changes. For development environment Node version requirements, use the `.nvmrc` file instead, which standardizes the development environment without impacting library consumers.

Applied to files:

  • tsconfig.json
📚 Learning: 2025-11-25T01:23:08.250Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.250Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : Use the `expectLastCalledWith` helper function instead of `expect(spy).toHaveBeenLastCalledWith(...)` for better typing and autocompletion

Applied to files:

  • test/helper/expectStackGroups.ts
📚 Learning: 2025-11-25T01:23:08.250Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.250Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : Prefer to use the `createSelectorTestCase` helper function when writing or modifying tests

Applied to files:

  • test/helper/expectStackGroups.ts
📚 Learning: 2025-11-25T01:23:08.250Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.250Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : Verify the number of selector calls using the spy object from `createSelectorTestCase` to spot unnecessary re-renders and improve performance

Applied to files:

  • test/helper/expectStackGroups.ts
📚 Learning: 2025-11-25T01:23:08.250Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.250Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : Use `vi.useFakeTimers()` in all tests due to Redux autoBatchEnhancer dependency on timers and `requestAnimationFrame`

Applied to files:

  • test/helper/expectStackGroups.ts
📚 Learning: 2025-11-25T01:22:59.729Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-25T01:22:59.729Z
Learning: Applies to storybook/stories/**/*.stories.tsx : Use Storybook for smoke tests and add play functions with assertions for actual tests

Applied to files:

  • test/helper/expectStackGroups.ts
  • storybook/stories/API/chart/RadialBarChart.stories.tsx
📚 Learning: 2025-11-25T01:22:59.729Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-25T01:22:59.729Z
Learning: Applies to storybook/stories/**/*.stories.tsx : Update Storybook stories when APIs have been changed to ensure they work as expected

Applied to files:

  • storybook/stories/API/chart/Treemap.stories.tsx
  • storybook/stories/Examples/cartesian/Area/AreaWithCustomLabel.stories.tsx
  • storybook/stories/API/chart/RadialBarChart.stories.tsx
📚 Learning: 2025-12-26T15:59:11.254Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: DEVELOPING.md:0-0
Timestamp: 2025-12-26T15:59:11.254Z
Learning: Applies to **/*.stories.{ts,tsx} : When adding new Storybook stories, prioritize high-fidelity examples that you want published on the website and in the Storybook UI. Use low-fidelity tests in unit tests or visual regression tests instead to avoid exceeding the Chromatic open source plan limits.

Applied to files:

  • storybook/stories/API/chart/Treemap.stories.tsx
📚 Learning: 2025-12-16T08:12:06.809Z
Learnt from: PavelVanecek
Repo: recharts/recharts PR: 6783
File: test/util/ChartUtils.spec.tsx:15-16
Timestamp: 2025-12-16T08:12:06.809Z
Learning: In tests (files under any test directory, e.g., test/, __tests__/, etc.), allow importing internal module paths (e.g., ../../src/...) and do not require imports to use the public API entry point (src/index.ts). The public API import restriction should apply only to non-test code. During reviews, accept internal imports in test files and enforce the public API pattern only for non-test code.

Applied to files:

  • test/chart/LineChart.spec.tsx
📚 Learning: 2025-11-23T13:30:10.395Z
Learnt from: PavelVanecek
Repo: recharts/recharts PR: 6669
File: www/src/docs/exampleComponents/ScatterChart/ScatterChartWithLabels.tsx:2-2
Timestamp: 2025-11-23T13:30:10.395Z
Learning: The `TooltipIndex` type from recharts is defined in `src/state/tooltipSlice.ts` but is not currently exported from the public API entry points. It should not be imported from `recharts/types/state/tooltipSlice` as this is an internal implementation path. An ESLint rule is needed to prevent regressions.

Applied to files:

  • test/chart/LineChart.spec.tsx
  • src/chart/Treemap.tsx
  • www/src/components/GuideView/ZIndex/PrahaMetro.tsx
  • src/index.ts
📚 Learning: 2025-11-25T01:22:59.729Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-25T01:22:59.729Z
Learning: Applies to test/component/**/*.spec.tsx : Use React Testing Library for testing component interactions and behavior upon rendering

Applied to files:

  • test/chart/LineChart.spec.tsx
📚 Learning: 2025-12-26T15:59:11.254Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: DEVELOPING.md:0-0
Timestamp: 2025-12-26T15:59:11.254Z
Learning: For release testing, use `yalc` to test Recharts changes in a test package as close as possible to the results of `npm publish` to ensure no unintended breaking changes are published.

Applied to files:

  • test/chart/LineChart.spec.tsx
📚 Learning: 2025-12-14T13:58:49.197Z
Learnt from: PavelVanecek
Repo: recharts/recharts PR: 6771
File: src/shape/Curve.tsx:39-40
Timestamp: 2025-12-14T13:58:49.197Z
Learning: In the recharts codebase, hooks like useAppSelector and other hooks (e.g., useChartLayout()) return undefined when used outside Redux Provider context, instead of throwing. This enables components that call these hooks, such as Curve, to operate in standalone mode by falling back to prop values. During code reviews, ensure TSX files gracefully handle undefined results from hooks and implement fallbacks (e.g., via default props or explicit prop-based values) rather than assuming the hook is always within Provider.

Applied to files:

  • src/chart/Treemap.tsx
  • src/shape/Curve.tsx
  • src/component/LabelList.tsx
📚 Learning: 2025-12-08T08:23:26.261Z
Learnt from: PavelVanecek
Repo: recharts/recharts PR: 6750
File: src/state/selectors/axisSelectors.ts:593-602
Timestamp: 2025-12-08T08:23:26.261Z
Learning: In the recharts codebase, `DataKey<any>` is an intentional exception to the "no any" rule while proper typing is being developed. This should not be flagged in reviews.

Applied to files:

  • src/component/LabelList.tsx
📚 Learning: 2025-12-14T13:58:58.361Z
Learnt from: PavelVanecek
Repo: recharts/recharts PR: 6771
File: src/shape/Curve.tsx:39-40
Timestamp: 2025-12-14T13:58:58.361Z
Learning: In the recharts codebase, `useAppSelector` and hooks like `useChartLayout()` are designed to return `undefined` when used outside Redux Provider context, rather than throwing errors. This allows components like `Curve` that call these hooks to work standalone by falling back to prop values.

Applied to files:

  • storybook/stories/Examples/cartesian/Area/AreaWithCustomLabel.stories.tsx
  • storybook/stories/API/chart/RadialBarChart.stories.tsx
📚 Learning: 2025-11-19T14:08:01.728Z
Learnt from: PavelVanecek
Repo: recharts/recharts PR: 6659
File: www/src/components/GuideView/Performance/index.tsx:232-250
Timestamp: 2025-11-19T14:08:01.728Z
Learning: In Recharts version 3.4.2, object-as-prop optimizations were introduced to reduce unnecessary re-renders when new object references are passed as props. This affects the recommendation for the `react-perf/jsx-no-new-object-as-prop` ESLint rule.

Applied to files:

  • storybook/stories/Examples/cartesian/Area/AreaWithCustomLabel.stories.tsx
🧬 Code graph analysis (7)
test/helper/expectStackGroups.ts (1)
src/util/stacks/stackTypes.ts (1)
  • StackDataPoint (51-51)
storybook/stories/API/chart/Treemap.stories.tsx (2)
src/chart/Treemap.tsx (1)
  • TreemapNode (60-74)
src/index.ts (1)
  • TreemapNode (105-105)
src/chart/Treemap.tsx (3)
src/index.ts (2)
  • TreemapNode (105-105)
  • TooltipIndex (17-17)
src/state/tooltipSlice.ts (2)
  • TooltipPayloadSearcher (46-51)
  • TooltipIndex (39-39)
src/util/DataUtils.ts (1)
  • isNan (16-19)
www/src/components/GuideView/ZIndex/PrahaMetro.tsx (2)
src/component/LabelList.tsx (1)
  • LabelListEntry (15-27)
src/index.ts (1)
  • LabelListEntry (29-29)
src/shape/Curve.tsx (2)
src/util/types.ts (3)
  • LayoutType (57-57)
  • Coordinate (125-128)
  • NullableCoordinate (130-133)
src/util/DataUtils.ts (1)
  • upperFirst (189-195)
src/component/LabelList.tsx (2)
src/util/types.ts (1)
  • DataKey (90-90)
src/util/ChartUtils.ts (1)
  • getValueByDataKey (44-62)
storybook/stories/API/chart/RadialBarChart.stories.tsx (1)
src/index.ts (1)
  • LegendPayload (14-14)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Build, Test, Pack
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (25)
test/helper/expectStackGroups.ts (4)

5-10: LGTM! Excellent use of unknown for optional properties.

The SyncExpectationResult interface properly standardizes the matcher return type and correctly uses unknown for the optional actual and expected properties, aligning with the coding guideline to prefer unknown over any.


65-83: LGTM! Improved error handling and type safety.

The explicit SyncExpectationResult return type and the error guard on line 80 improve both type safety and runtime robustness. The previous direct access to e.message could have failed at runtime if the caught value wasn't an Error instance.


85-103: LGTM! Consistent type safety improvements.

The matcher follows the same robust pattern as rechartsStackedDataMatcher, with explicit return typing and safe error message extraction on line 100.


105-123: LGTM! Completes the consistent refactor across all matchers.

All three matchers now use the same standardized, type-safe pattern. The changes throughout this file successfully avoid any types and provide explicit type annotations, aligning perfectly with the strict TypeScript configuration goals of this PR.

src/chart/Treemap.tsx (5)

71-73: LGTM! Index signature improvement aligns with TypeScript best practices.

The change from any to unknown for the index signature follows the project's coding guidelines. The addition of the root field enables proper parent navigation in the treemap hierarchy.

Based on learnings, this aligns with the guideline to prefer unknown over any.


91-96: Verify breaking change to public API is intentional.

The signature change from TooltipPayloadSearcher<TreemapNode, TreemapNode> to generic TooltipPayloadSearcher (accepting/returning unknown) is a breaking change for consumers who rely on the typed signature. This reduces type safety for callers.

If this change is necessary for strict TypeScript compliance, ensure it's documented in the PR description or migration notes.


146-153: LGTM! Improved type safety by using typed field.

The change from child[NODE_VALUE_KEY] to child.value and the safe numeric value extraction with type checking and fallbacks improve type safety and align with strict TypeScript mode.


877-878: LGTM! Safe name extraction with proper type narrowing.

The defensive pattern using get() with a fallback and subsequent type narrowing ensures name is always a string, preventing runtime errors from unexpected data types.


913-926: LGTM! Proper runtime validation prevents potential errors.

The type guard usage ensures activeNode is valid before accessing its properties, preventing runtime errors in touch event handling.

www/src/docs/exampleComponents/TreeMap/CustomContentTreemap.tsx (1)

152-152: LGTM! Safe access pattern prevents potential runtime errors.

The optional chaining with nullish coalescing operator properly handles the case where root.children is null, which is allowed by the TreemapNode interface definition.

src/index.ts (1)

29-29: LGTM! Public API export follows established patterns.

The addition of LabelListEntry to the public API exports enables consumers to properly type their label list entries, improving TypeScript support.

storybook/stories/API/chart/Treemap.stories.tsx (2)

4-4: LGTM! Proper import from public API.

The import of TreemapNode from the public API entry point aligns with the coding guideline that all imports from recharts should use the public API entry point.

Based on learnings, this follows the project's import conventions.


152-163: LGTM! Improved type safety and defensive coding.

The explicit TreemapNode type annotation on the content function parameter and the safe access pattern for root.children?.length ?? 1 improve type safety and prevent potential runtime errors.

Based on learnings, updating Storybook stories when APIs change ensures they work as expected.

test/chart/LineChart.spec.tsx (1)

9-9: LGTM! Using public type improves test type safety.

Importing and using LabelProps from the public API instead of an inline type annotation improves maintainability and ensures tests stay in sync with the component API.

Also applies to: 495-502

storybook/stories/API/chart/RadialBarChart.stories.tsx (2)

6-15: LGTM! Explicit type imports improve type safety.

The addition of DefaultLegendContentProps and LegendPayload types provides proper typing for the Legend payload handling, aligning with the project's strict TypeScript configuration.


47-47: LGTM! Explicit type annotations align with strict TypeScript configuration.

The explicit typing of useState, the Legend content function parameter, and the payload mapping improves type safety and follows the coding guidelines for explicit function parameter types.

Also applies to: 63-63, 65-65

tsconfig.json (1)

2-2: LGTM! Centralizing configuration via base tsconfig.

Extending from tsconfig.base.json is a good practice that centralizes strict compiler options and ensures consistency across the project's TypeScript configurations.

storybook/stories/Examples/cartesian/Area/AreaWithCustomLabel.stories.tsx (1)

2-2: LGTM! Using public LabelProps type.

Replacing the inline type annotation with the public LabelProps type improves consistency and maintainability. The destructuring of { index, x, y } works correctly with the LabelProps interface.

Also applies to: 12-12

src/component/LabelList.tsx (4)

15-27: LGTM! Exporting LabelListEntry improves type safety.

Making LabelListEntry a public interface enables consumers to properly type their code when working with label list entries, as demonstrated in the storybook files and www components.


25-25: LGTM! Replacing any with unknown follows coding guidelines.

The change from Record<string, any> to Record<string, unknown> for the payload property aligns with the project's coding guidelines that prefer unknown over any. The payload is intentionally generic because its shape depends on user-provided data.

Based on learnings, prefer unknown over any and refine the type in TypeScript.

Also applies to: 80-80


37-37: LGTM! Type hierarchy updates maintain consistency.

The updates to CartesianLabelListEntry, PolarLabelListEntry, and defaultAccessor to use the new LabelListEntry base interface maintain type consistency across the component while preserving the existing public API surface.

Also applies to: 46-50, 148-148


184-184: LGTM! Simplified data access.

The updated getValueByDataKey call passing entry.payload directly (instead of entry && entry.payload) is cleaner, as the entry parameter is guaranteed to be defined at this point in the map iteration.

src/shape/Curve.tsx (3)

23-24: LGTM: Clear and specific import names.

The renamed imports (D3AreaCurve, D3LineCurve) improve clarity by making the D3 origin explicit and avoiding potential naming conflicts with other Area/Line types in the codebase.


91-104: LGTM: Improved type safety and defensive coding.

The explicit return type on line 91 clarifies the function contract, and the null guard on lines 100-102 correctly handles the case where the dynamically constructed key might not exist in CURVE_FACTORIES, allowing the fallback on line 104 to handle it appropriately.


217-217: The ts-expect-error directives are an appropriate workaround for a known d3-shape type limitation.

The code correctly documents why type suppression is necessary: d3's single-generic parameter prevents expressing how .defined() transforms the function to accept nullable inputs while filtering them internally. Since:

  • @types/d3-shape (3.1.6) has not resolved this limitation
  • The coding guidelines forbid as assertions (the alternative)
  • The runtime behavior is correct (.defined() filters nulls before passing to getX/getY)

The ts-expect-error approach with detailed comments is the appropriate solution. No changes needed.

Comment on lines +215 to 222
valueAccessor={(entry: LabelListEntry) => {
// @ts-expect-error Recharts does not have types for the payload property
const label: string | undefined = entry.payload?.name;
if (label != null && customLabels.includes(label)) {
return undefined;
}
// @ts-expect-error untyped payload
return entry.payload.name;
return label;
}}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Remove @ts-expect-error and use proper type narrowing.

The comment "Recharts does not have types for the payload property" is misleading. The payload property IS typed as Record<string, unknown> | null | undefined in LabelListEntry. The issue is that accessing entry.payload?.name returns unknown, which cannot be directly assigned to string | undefined.

Instead of suppressing the error, use proper type narrowing:

🔎 Proposed fix with proper type narrowing
-        valueAccessor={(entry: LabelListEntry) => {
-          // @ts-expect-error Recharts does not have types for the payload property
-          const label: string | undefined = entry.payload?.name;
+        valueAccessor={(entry: LabelListEntry) => {
+          const label = typeof entry.payload?.name === 'string' ? entry.payload.name : undefined;
           if (label != null && customLabels.includes(label)) {
             return undefined;
           }
           return label;
         }}

Based on coding guidelines, @ts-expect-error comments indicate technical debt that should be addressed. The as type assertion is not allowed except for as const, and this approach uses a proper type guard instead.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
valueAccessor={(entry: LabelListEntry) => {
// @ts-expect-error Recharts does not have types for the payload property
const label: string | undefined = entry.payload?.name;
if (label != null && customLabels.includes(label)) {
return undefined;
}
// @ts-expect-error untyped payload
return entry.payload.name;
return label;
}}
valueAccessor={(entry: LabelListEntry) => {
const label = typeof entry.payload?.name === 'string' ? entry.payload.name : undefined;
if (label != null && customLabels.includes(label)) {
return undefined;
}
return label;
}}
🤖 Prompt for AI Agents
In www/src/components/GuideView/ZIndex/PrahaMetro.tsx around lines 215 to 222,
remove the @ts-expect-error and replace the unchecked access to
entry.payload?.name with a proper type guard: first read payload =
entry.payload, check payload != null and typeof payload === 'object' and then
check typeof (payload as Record<string, unknown>)['name'] === 'string' (or
equivalently typeof payload.name === 'string') before assigning to label so
label is string | undefined; do not use any "as" casts except as const and
ensure the resulting code returns undefined for non-string names and the string
for valid names.

@codecov
Copy link

codecov bot commented Jan 1, 2026

Codecov Report

❌ Patch coverage is 82.35294% with 33 lines in your changes missing coverage. Please review.
✅ Project coverage is 93.81%. Comparing base (1898abb) to head (d5e4eba).
⚠️ Report is 5 commits behind head on main.

Files with missing lines Patch % Lines
src/cartesian/Funnel.tsx 46.15% 14 Missing ⚠️
www/src/components/GuideView/ZIndex/PrahaMetro.tsx 0.00% 5 Missing ⚠️
src/cartesian/getTicks.ts 85.71% 4 Missing ⚠️
src/cartesian/Brush.tsx 87.50% 2 Missing ⚠️
src/cartesian/getEquidistantTicks.ts 71.42% 2 Missing ⚠️
src/chart/RechartsWrapper.tsx 87.50% 2 Missing ⚠️
src/component/ResponsiveContainer.tsx 60.00% 2 Missing ⚠️
src/cartesian/ReferenceLine.tsx 85.71% 1 Missing ⚠️
src/component/Tooltip.tsx 50.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #6842      +/-   ##
==========================================
- Coverage   93.85%   93.81%   -0.05%     
==========================================
  Files         531      531              
  Lines       48982    49076      +94     
  Branches     5133     5163      +30     
==========================================
+ Hits        45972    46040      +68     
- Misses       3003     3029      +26     
  Partials        7        7              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions
Copy link
Contributor

github-actions bot commented Jan 1, 2026

Staging Deployment Details

These deployments will remain available for 30 days.

To update snapshots: Comment /update-snapshots on this PR to automatically update the baseline screenshots.

@codecov
Copy link

codecov bot commented Jan 2, 2026

Bundle Report

Changes will increase total bundle size by 8.56kB (0.31%) ⬆️. This is within the configured threshold ✅

Detailed changes
Bundle name Size Change
recharts/bundle-cjs 1.2MB 3.72kB (0.31%) ⬆️
recharts/bundle-es6 1.04MB 3.7kB (0.36%) ⬆️
recharts/bundle-umd 527.8kB 1.15kB (0.22%) ⬆️

Affected Assets, Files, and Routes:

view changes for bundle: recharts/bundle-umd

Assets Changed:

Asset Name Size Change Total Size Change (%)
Recharts.js 1.15kB 527.8kB 0.22%
view changes for bundle: recharts/bundle-es6

Assets Changed:

Asset Name Size Change Total Size Change (%)
chart/Sankey.js 92 bytes 29.61kB 0.31%
chart/Treemap.js 477 bytes 27.85kB 1.74%
cartesian/Brush.js 364 bytes 26.89kB 1.37%
cartesian/Line.js 130 bytes 24.88kB 0.53%
polar/Pie.js 114 bytes 24.5kB 0.47%
cartesian/Funnel.js 609 bytes 17.57kB 3.59%
cartesian/CartesianGrid.js 24 bytes 15.23kB 0.16%
chart/RechartsWrapper.js 698 bytes 13.16kB 5.6% ⚠️
cartesian/ReferenceLine.js 131 bytes 9.93kB 1.34%
component/ResponsiveContainer.js 76 bytes 9.57kB 0.8%
component/Text.js 50 bytes 9.33kB 0.54%
cartesian/getTicks.js 382 bytes 7.22kB 5.59% ⚠️
shape/Curve.js 297 bytes 6.47kB 4.81%
component/LabelList.js -9 bytes 5.75kB -0.16%
cartesian/getEquidistantTicks.js 259 bytes 4.6kB 5.97% ⚠️
util/scale/RechartsScale.js 1 bytes 3.25kB 0.03%
state/optionsSlice.js 4 bytes 1.2kB 0.33%
view changes for bundle: recharts/bundle-cjs

Assets Changed:

Asset Name Size Change Total Size Change (%)
chart/Sankey.js 92 bytes 31.32kB 0.29%
chart/Treemap.js 477 bytes 29.53kB 1.64%
cartesian/Brush.js 364 bytes 28.19kB 1.31%
cartesian/Line.js 130 bytes 26.49kB 0.49%
polar/Pie.js 114 bytes 26.23kB 0.44%
cartesian/Funnel.js 609 bytes 19.05kB 3.3%
cartesian/CartesianGrid.js 24 bytes 16.53kB 0.15%
chart/RechartsWrapper.js 686 bytes 14.98kB 4.8%
cartesian/ReferenceLine.js 131 bytes 11.34kB 1.17%
component/ResponsiveContainer.js 76 bytes 10.97kB 0.7%
component/Text.js 50 bytes 10.6kB 0.47%
shape/Curve.js 297 bytes 7.59kB 4.07%
cartesian/getTicks.js 382 bytes 7.46kB 5.4% ⚠️
component/LabelList.js -9 bytes 6.99kB -0.13%
cartesian/getEquidistantTicks.js 259 bytes 4.84kB 5.65% ⚠️
util/scale/RechartsScale.js 1 bytes 4.1kB 0.02%
state/optionsSlice.js 35 bytes 1.51kB 2.37%

@ckifer ckifer merged commit 8bb5aa4 into main Jan 2, 2026
40 of 44 checks passed
@ckifer ckifer deleted the ts-strict branch January 2, 2026 18:36
@coderabbitai coderabbitai bot mentioned this pull request Jan 24, 2026
7 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants