Skip to content

[DateTimePicker] Publish sistent's own props type instead of the optional peer's - #1754

Open
Valyrian-Code wants to merge 1 commit into
layer5io:masterfrom
Valyrian-Code:fix/1749-datetimepicker-props-optional-peer
Open

[DateTimePicker] Publish sistent's own props type instead of the optional peer's#1754
Valyrian-Code wants to merge 1 commit into
layer5io:masterfrom
Valyrian-Code:fix/1749-datetimepicker-props-optional-peer

Conversation

@Valyrian-Code

@Valyrian-Code Valyrian-Code commented Jul 26, 2026

Copy link
Copy Markdown

Notes for Reviewers

This PR fixes #1749

@mui/x-date-pickers is an optional peer, so a consumer is entitled to skip it, but the published declaration bundle named it and the reference then failed two ways: TS2307 under skipLibCheck: false, and a silent any under skipLibCheck: true.

Removing the re-export alone was not enough

The issue suggests dropping the barrel's export type { DateTimePickerProps }. I tried exactly that first and rebuilt — dist/index.d.ts still had:

import { DateTimePickerProps } from '@mui/x-date-pickers/DateTimePicker';

because the exported component was itself declared with that type:

declare const DateTimePicker: React.ForwardRefExoticComponent<
  DateTimePickerProps & React.RefAttributes<HTMLDivElement>
>;

so the import survived to serve that declaration. Two references, not one — it went 2 → 1, which means the @mui/x-date-pickers entry in OPTIONAL_PEERS_ON_THE_RECORD still could not be deleted (the guard asserts each exemption is still needed and fails on a stale one).

What this does instead

DateTimePicker now publishes sistent's own DateTimePickerProps interface rather than aliasing the peer's. Named props stay checked; a string index signature keeps every other picker prop accepted and forwarded, so this loosens rather than narrows the public surface. MUI's real type stays as a module-local import type used only in positions the declaration bundle erases, so the runtime React.lazy deferral is untouched.

One non-obvious detail, flagged because it is easy to "simplify" away in review: the forwardRef results are annotated explicitly with a DateTimePickerComponent alias. Left to inference, forwardRef<T, P> returns ForwardRefExoticComponent<PropsWithoutRef<P> & ...>, and PropsWithoutRef<P> resolves to Omit<P, 'ref'> when P has an index signature — whose keyof P is string | number, collapsing the interface to { [x: string]: unknown } and silently discarding every named prop's type. <DateTimePicker value="not a date" /> then compiles clean, which would be worse than the bug being fixed. The built output is declare const DateTimePicker: DateTimePickerComponent;, not the collapsed Omit<..., "ref"> form.

I also reworded a comment in DateTimePicker.tsx because my first draft quoted a literal import ... from '@mui/x-date-pickers/...' statement in prose, which optionalPeerDependencies.test.ts correctly flagged — that scanner deliberately does not strip comments. Reworded the prose rather than touching the guard.

Verification

Against a clean consumer built from npm pack, with both optional peers confirmed absent:

  • Both dist/index.d.ts and dist/index.d.mts reference @mui/x-date-pickers zero times (specifier positions, comments stripped, same detector the guard uses).
  • The probe from the issue no longer compiles, which is the fix — the type is real rather than any:
    probe.ts(4,14): error TS2322: Type 'true' is not assignable to type 'false'.
    
  • require('@sistent/sistent') still loads with the peers absent, so the runtime half is unaffected.
  • Under skipLibCheck: false the only remaining TS2307s come from @meshery/schemas referencing @reduxjs/toolkit — the pre-existing UNDECLARED_BY_DESIGN exemption, unrelated to this change.
  • Consumer compatibility spot-checks: spreading a full MUI DateTimePickerProps value into the component still compiles, as do two-parameter onChange handlers, views / ampm / slotProps / sx / ref / data-testid, while value={'not a date'} and onChange={(n: number) => {}} still error.
  • CI=1 jest: 466 passing, 26 suites. eslint . clean. prettier --check clean on the touched files.

Because the count is now zero, the @mui/x-date-pickers entry is deleted from OPTIONAL_PEERS_ON_THE_RECORD and the surrounding comment updated — react is the sole remaining entry and it is permanent rather than a deferred fix, which the old wording ("the fix is to stop naming them in the public type surface") no longer described. AGENTS.md gets the same correction plus a short note that dropping a type re-export does not on its own remove a peer an exported component is still typed with.

One known limitation

Assigning a MUI props value to sistent's DateTimePickerProps in a non-JSX position stops compiling:

const p: DateTimePickerProps = someMuiPropsValue; // index signature missing

An interface source gets no implicit index signature. JSX spread — the common case — works. This cannot be fixed without dropping the index signature, which would break the far more common spread and MUI-only-prop cases, so I took this trade deliberately.

Happy to switch to the smaller variant instead — dropping the public DateTimePickerProps export entirely and keeping the props interface non-exported — which matches the issue's literal wording, also reaches zero, and avoids the index-signature loosening. I raised both options on the issue; this is the one that keeps the existing public type working, but it is your call and the change is small either way.

Signed commits

  • Yes, I signed my commits.

Summary by CodeRabbit

  • Bug Fixes

    • Improved the published TypeScript declarations for DateTimePicker.
    • DateTimePicker consumers no longer need the optional date-picker package’s types exposed in the component’s public props.
    • Added clearer local prop typing while preserving existing DateTimePicker behavior and configuration options.
  • Documentation

    • Clarified guidance for handling optional peer dependencies and public type exports.

…al peer's

`dist/index.d.ts` named `@mui/x-date-pickers` in two places: the barrel's
`export type { DateTimePickerProps }` re-export, and the exported component's
own `ForwardRefExoticComponent<DateTimePickerProps & ...>` declaration. The peer
is optional, so a consumer is entitled to skip it, and the reference then fails
two ways: `TS2307` under `skipLibCheck: false`, and a silent `any` under
`skipLibCheck: true`.

Removing only the re-export leaves the second reference, which keeps the import
alive on its own, so declare sistent's own `DateTimePickerProps` instead. Named
props stay checked; a string index signature keeps every other picker prop
accepted and forwarded, so this loosens rather than narrows the public surface.

`forwardRef`'s result is annotated explicitly because `PropsWithoutRef<P>`
resolves to `Omit<P, 'ref'>` for a `P` with an index signature, which collapses
the interface to `{ [x: string]: unknown }` and silently discards every named
prop's type.

With the peer absent, the issue's own `IsAny<DateTimePickerProps>` probe now
fails to compile, which is the fix: the type is real rather than `any`. Both
declaration bundles reference the peer zero times, so the
`@mui/x-date-pickers` entry in `OPTIONAL_PEERS_ON_THE_RECORD` is deleted -- the
guard asserts each exemption is still needed and would fail on a stale one.

Signed-off-by: Rajveer Bishnoi <260926695+Valyrian-Code@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 26, 2026 21:02

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: caef4e51-7756-484a-9f63-0cd05c767b6d

📥 Commits

Reviewing files that changed from the base of the PR and between 846866a and f63d57c.

📒 Files selected for processing (4)
  • AGENTS.md
  • src/__testing__/publishedTypeSurfaceDependencies.test.ts
  • src/base/DateTimePicker/DateTimePicker.tsx
  • src/base/DateTimePicker/index.tsx

📝 Walkthrough

Walkthrough

DateTimePicker now exports local props typings instead of exposing @mui/x-date-pickers types. Its lazy runtime rendering remains intact, while the published declaration dependency test removes the MUI picker exemption and documentation records the type-surface rule.

Changes

Optional peer type-surface cleanup

Layer / File(s) Summary
Public DateTimePicker contract
src/base/DateTimePicker/DateTimePicker.tsx, src/base/DateTimePicker/index.tsx
Exports local DateTimePickerProps, types the lazy and forwarded-ref components with it, and casts props only when rendering the MUI picker.
Dependency surface validation
src/__testing__/publishedTypeSurfaceDependencies.test.ts, AGENTS.md
Removes @mui/x-date-pickers from the optional-peer exemption list and documents that peer-only type re-exports do not prevent declaration-level peer references.

Estimated code review effort: 2 (Simple) | ~15 minutes

Possibly related PRs

Suggested labels: area/ci

Suggested reviewers: copilot, codeahmedjamil

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the main change: publishing Sistent’s own DateTimePicker props instead of the optional peer’s type.
Linked Issues check ✅ Passed The PR removes the optional @mui/x-date-pickers type dependency from the public surface and updates the exemption guard as #1749 requested.
Out of Scope Changes check ✅ Passed The added doc and test updates directly support the type-surface fix and do not introduce unrelated scope.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

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.

Barrel re-exports DateTimePickerProps from the optional peer @mui/x-date-pickers, so the type is any for consumers who skip it

2 participants