Skip to content

Add external generics to Area#6993

Merged
PavelVanecek merged 1 commit intomainfrom
Area-typed
Feb 16, 2026
Merged

Add external generics to Area#6993
PavelVanecek merged 1 commit intomainfrom
Area-typed

Conversation

@PavelVanecek
Copy link
Collaborator

@PavelVanecek PavelVanecek commented Feb 11, 2026

Description

Use the new generics to allow strong typing for Area. Other graphical items are coming in separate PR.

Later I will also add a new guide on how to use these.

Related Issue

#6645

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have added tests to cover my changes.
  • I have added a storybook story or VR test, or extended an existing story or VR test to show my changes

Summary by CodeRabbit

  • Refactor

    • Enhanced component type safety with improved generic typing support for better developer experience.
  • Tests

    • Expanded test coverage with comprehensive type validation scenarios.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 11, 2026

Walkthrough

Introduces generic type parameters (DataPointType, ValueAxisType) to the Area component's public API for type-safe data handling. Updates related test fixtures to align with new data shapes and explicit dataKey specifications.

Changes

Cohort / File(s) Summary
Area Component Generics
src/cartesian/Area.tsx
Adds exported generic types Props<DataPointType, ValueAxisType> and PropsWithDefaults<DataPointType, ValueAxisType>. Updates AreaFn, AreaImpl, and helper functions to support generic type parameters. Expands strokeWidth typing in internal components to accommodate broader type support.
Area Test Updates
test/cartesian/Area.spec.tsx, test/cartesian/Area.typed.spec.tsx
Updates Area tests to use new BaseValue type. Replaces minimal implicit-typing tests with comprehensive strongly-typed test suite covering implicit/explicit type parameters, dataKey validation (string and function), and explicit typing scenarios.
Selector Test Fixtures
test/state/selectors/axisSelectors.spec.tsx, test/state/selectors/dataSelectors.spec.tsx, test/state/selectors/selectors.spec.tsx
Updates Area component test fixtures to specify explicit dataKey values and corresponding data shapes (e.g., dataKey="x" with data={[{ x: ... }]}). Removes Customized component wrapper usage. Adjusts test expectations to match new data structures.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Possibly related PRs

Suggested labels

typescript

Suggested reviewers

  • ckifer
🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.11% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Add external generics to Area' clearly and concisely describes the main change: introducing generic type parameters to the Area component for improved type safety.
Description check ✅ Passed The description covers the key aspects: what was done (adding generics to Area), the motivation (strong typing), and related issue reference. However, some template sections are incomplete.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch Area-typed

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.

@codecov
Copy link

codecov bot commented Feb 11, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.10%. Comparing base (7b1b097) to head (a09935d).
⚠️ Report is 17 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #6993   +/-   ##
=======================================
  Coverage   90.10%   90.10%           
=======================================
  Files         522      522           
  Lines       38848    38850    +2     
  Branches     5347     5347           
=======================================
+ Hits        35004    35006    +2     
  Misses       3835     3835           
  Partials        9        9           

☔ 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.

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 (1)
src/cartesian/Area.tsx (1)

512-607: ⚠️ Potential issue | 🟡 Minor

Handle decimal strokeWidth values without truncation.

The current implementation uses parseInt, which truncates fractional string values (e.g., "1.5"1). Since strokeWidth accepts string | number and decimal values like strokeWidth={1.5} appear in the codebase, this causes incorrect clip rect sizing. Replace with Number.parseFloat and a finite check as proposed.

Proposed fix
 function VerticalRect({
   alpha,
   baseLine,
   points,
   strokeWidth,
 }: {
   alpha: number;
   points: ReadonlyArray<AreaPointItem>;
   baseLine: BaseLineType | undefined;
   strokeWidth: string | number | undefined;
 }) {
+  const strokeWidthValue = Number.parseFloat(`${strokeWidth}`);
+  const safeStrokeWidth = Number.isFinite(strokeWidthValue) ? strokeWidthValue : 1;
   const startY = points[0]?.y;
   const endY = points[points.length - 1]?.y;
   if (!isWellBehavedNumber(startY) || !isWellBehavedNumber(endY)) {
     return null;
   }
   const height = alpha * Math.abs(startY - endY);
   let maxX = Math.max(...points.map(entry => entry.x || 0));
@@
       <rect
         x={0}
         y={startY < endY ? startY : startY - height}
-        width={maxX + (strokeWidth ? parseInt(`${strokeWidth}`, 10) : 1)}
+        width={maxX + safeStrokeWidth}
         height={Math.floor(height)}
       />
     );
   }
@@
 function HorizontalRect({
   alpha,
   baseLine,
   points,
   strokeWidth,
 }: {
   alpha: number;
   points: ReadonlyArray<AreaPointItem>;
   baseLine: BaseLineType | undefined;
   strokeWidth: string | number | undefined;
 }) {
+  const strokeWidthValue = Number.parseFloat(`${strokeWidth}`);
+  const safeStrokeWidth = Number.isFinite(strokeWidthValue) ? strokeWidthValue : 1;
   const startX = points[0]?.x;
   const endX = points[points.length - 1]?.x;
   if (!isWellBehavedNumber(startX) || !isWellBehavedNumber(endX)) {
     return null;
   }
   const width = alpha * Math.abs(startX - endX);
   let maxY = Math.max(...points.map(entry => entry.y || 0));
@@
       <rect
         x={startX < endX ? startX : startX - width}
         y={0}
         width={width}
-        height={Math.floor(maxY + (strokeWidth ? parseInt(`${strokeWidth}`, 10) : 1))}
+        height={Math.floor(maxY + safeStrokeWidth)}
       />
     );
   }
🤖 Fix all issues with AI agents
In `@src/cartesian/Area.tsx`:
- Around line 1140-1143: Remove the `any` defaults and the `as` assertion on the
exported Area component: replace the current "export const Area =
React.memo(AreaFn, propsAreEqual) as <DataPointType = any, ValueAxisType =
any>(...)" pattern by giving Area an explicit generic type annotation (no `any`
defaults) and assign the memoized value to that typed const (e.g. declare export
const Area: <DataPointType, ValueAxisType>(props: Props<DataPointType,
ValueAxisType>) => ReactElement = React.memo(AreaFn, propsAreEqual)); keep the
existing AreaFn and propsAreEqual references and preserve the displayName
comment.

Comment on lines +1140 to +1143
export const Area = React.memo(AreaFn, propsAreEqual) as <DataPointType = any, ValueAxisType = any>(
props: Props<DataPointType, ValueAxisType>,
) => ReactElement;
// @ts-expect-error we need to set the displayName for debugging purposes
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

🧩 Analysis chain

🏁 Script executed:

# First, let's look at the Area.tsx file around the flagged lines
head -n 1150 src/cartesian/Area.tsx | tail -n 20

Repository: recharts/recharts

Length of output: 637


🏁 Script executed:

# Let's search for the AreaFn definition and understand the component structure
rg "const AreaFn|function AreaFn" src/cartesian/Area.tsx -A 5 -B 5

Repository: recharts/recharts

Length of output: 481


🏁 Script executed:

# Check if forwardRef is used in this file
rg "forwardRef" src/cartesian/Area.tsx -B 5 -A 5

Repository: recharts/recharts

Length of output: 43


🏁 Script executed:

# Let's also check other chart components to see if they use the same pattern
rg "export const.*React.memo.*as <" src/cartesian/ -A 3

Repository: recharts/recharts

Length of output: 392


🏁 Script executed:

# Check AreaChart to see the forwardRef pattern mentioned in learnings
head -n 50 src/chart/AreaChart.tsx | tail -n 30

Repository: recharts/recharts

Length of output: 1057


🏁 Script executed:

# Search for the export of AreaChart to see the pattern
rg "export const AreaChart" src/chart/AreaChart.tsx -A 3

Repository: recharts/recharts

Length of output: 227


🏁 Script executed:

# Search for other exported memoized components with explicit type annotations
rg "export const.*React.memo.*:" src/ -A 3 | head -50

Repository: recharts/recharts

Length of output: 43


🏁 Script executed:

# Check the current TypeScript version in the project
cat tsconfig.json | grep -A 2 "compilerOptions"

Repository: recharts/recharts

Length of output: 256


🏁 Script executed:

# Search for memoized components to understand the pattern better
rg "React.memo" src/ -A 5 | grep -A 5 "export const" | head -60

Repository: recharts/recharts

Length of output: 2201


🏁 Script executed:

# Check package.json for TypeScript version
grep -A 2 '"typescript"' package.json

Repository: recharts/recharts

Length of output: 164


🏁 Script executed:

# Check the Props type definition in Area.tsx to understand the generic structure
rg "type Props|interface Props" src/cartesian/Area.tsx -B 5 -A 10 | head -40

Repository: recharts/recharts

Length of output: 796


🏁 Script executed:

# Compare with another component like Scatter to see their Props definition
rg "type Props|interface Props" src/cartesian/Scatter.tsx -B 5 -A 10 | head -40

Repository: recharts/recharts

Length of output: 546


🏁 Script executed:

# Search for other generic memoized components with explicit type annotations
rg "React.memo.*\)" src/ -B 2 | grep -B 10 "as <" | head -80

Repository: recharts/recharts

Length of output: 608


🏁 Script executed:

# Look for any other components using generic type parameters with explicit annotations
rg "export const.*ComponentType<.*<" src/ -A 2

Repository: recharts/recharts

Length of output: 43


🏁 Script executed:

# Check if Area needs to be generic or if it can be simplified like Scatter
rg "AreaFn<" src/cartesian/Area.tsx -B 5 -A 10

Repository: recharts/recharts

Length of output: 669


🏁 Script executed:

# Check if any component uses explicit generic type annotation on React.memo export
rg "export const.*React.memo.*<.*>" src/ -A 3 | head -50

Repository: recharts/recharts

Length of output: 392


🏁 Script executed:

# Let's verify if the proposed syntax would work by checking TypeScript docs examples
# For now, let's see if there are any comments explaining why Area uses this pattern
rg -B 10 "export const Area = React.memo" src/cartesian/Area.tsx | head -30

Repository: recharts/recharts

Length of output: 294


🏁 Script executed:

# Final check: look for any explicit generic function type annotations in the codebase to validate the proposed syntax
rg ": <.*>(.*) => " src/ | head -20

Repository: recharts/recharts

Length of output: 43


Remove the any defaults and the as assertion on the exported Area component.

The any defaults and as assertion violate the no-any and no-as coding guidelines. The documented exception for as assertions applies only to generic forwardRef chart components (like AreaChart), not to memoized components. Use an explicit generic type annotation instead:

-export const Area = React.memo(AreaFn, propsAreEqual) as <DataPointType = any, ValueAxisType = any>(
-  props: Props<DataPointType, ValueAxisType>,
-) => ReactElement;
+export const Area: <DataPointType = unknown, ValueAxisType = unknown>(
+  props: Props<DataPointType, ValueAxisType>,
+) => ReactElement = React.memo(AreaFn, propsAreEqual);
🤖 Prompt for AI Agents
In `@src/cartesian/Area.tsx` around lines 1140 - 1143, Remove the `any` defaults
and the `as` assertion on the exported Area component: replace the current
"export const Area = React.memo(AreaFn, propsAreEqual) as <DataPointType = any,
ValueAxisType = any>(...)" pattern by giving Area an explicit generic type
annotation (no `any` defaults) and assign the memoized value to that typed const
(e.g. declare export const Area: <DataPointType, ValueAxisType>(props:
Props<DataPointType, ValueAxisType>) => ReactElement = React.memo(AreaFn,
propsAreEqual)); keep the existing AreaFn and propsAreEqual references and
preserve the displayName comment.

@codecov
Copy link

codecov bot commented Feb 11, 2026

Bundle Report

Changes will decrease total bundle size by 106 bytes (-0.0%) ⬇️. This is within the configured threshold ✅

Detailed changes
Bundle name Size Change
recharts/bundle-cjs 1.25MB -62 bytes (-0.0%) ⬇️
recharts/bundle-es6 1.09MB -33 bytes (-0.0%) ⬇️
recharts/bundle-umd 539.26kB -11 bytes (-0.0%) ⬇️

Affected Assets, Files, and Routes:

view changes for bundle: recharts/bundle-es6

Assets Changed:

Asset Name Size Change Total Size Change (%)
cartesian/Area.js -33 bytes 27.43kB -0.12%
view changes for bundle: recharts/bundle-umd

Assets Changed:

Asset Name Size Change Total Size Change (%)
Recharts.js -11 bytes 539.26kB -0.0%
view changes for bundle: recharts/bundle-cjs

Assets Changed:

Asset Name Size Change Total Size Change (%)
cartesian/Area.js -62 bytes 29.27kB -0.21%

@github-actions
Copy link
Contributor

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.

@PavelVanecek PavelVanecek merged commit 5e33c7b into main Feb 16, 2026
84 of 85 checks passed
@PavelVanecek PavelVanecek deleted the Area-typed branch February 16, 2026 11:53
ckifer pushed a commit that referenced this pull request Feb 17, 2026
## Description

Same as #6993 but for Bar


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Refactor**
* Bar component TypeScript typing enhanced with improved generic type
parameter support, providing better type inference and validation.

* **Tests**
* Added extensive type safety test coverage for the Bar component across
multiple data typing scenarios to ensure compile-time correctness.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
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.

1 participant