Skip to content

Conversation

@taearls
Copy link
Contributor

@taearls taearls commented Nov 1, 2025

Fixes #20948

Fix Plugin Type Compatibility with exactOptionalPropertyTypes

Problem

When TypeScript's exactOptionalPropertyTypes is enabled, users cannot spread Rollup plugins into Vite config:

plugins: [
  {
    enforce: "pre",
    ...virtual({ "foo": "" })  // ❌ Type error
  }
]

Error: Type 'Plugin<any>' is not assignable to type 'PluginOption'

Root Cause

Rollup v4.43.0 added support for exactOptionalPropertyTypes by explicitly marking optional properties with | undefined. Vite's Plugin interface didn't match these updated type definitions, causing incompatibility.

Solution

Add | undefined to Vite's optional hook parameters (ssr, scan) that extend Rollup's plugin hooks. This aligns with Rollup's type definitions while maintaining backward compatibility.

Changes

  • resolveId hook: ssr?: booleanssr?: boolean | undefined
  • load hook: ssr?: booleanssr?: boolean | undefined
  • transform hook: ssr?: booleanssr?: boolean | undefined
  • Internal: scan?: booleanscan?: boolean | undefined

Result

✅ Rollup plugins can be spread into Vite config
✅ Compatible with exactOptionalPropertyTypes: true
✅ Full type compatibility with Rollup v4.43.0+
✅ No breaking changes for existing users

…pertyTypes compatibility

Add `| undefined` to optional properties in plugin hook type definitions
to support TypeScript's exactOptionalPropertyTypes compiler option.

This ensures compatibility with Rollup plugins that have updated their
types to explicitly include undefined on optional properties.

Changes:
- resolveId: Add | undefined to ssr, scan, and filter.id properties
- load: Add | undefined to ssr and filter.id properties
- transform: Add | undefined to ssr, filter.id, and filter.code properties

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@taearls taearls force-pushed the 20948/rollup-plugin-virtual-fixes branch from 8984571 to cf92d4f Compare November 1, 2025 18:42
taearls and others added 2 commits November 1, 2025 13:54
Fix type compatibility with Rollup's HookFilterExtension by adding
| undefined to the filter property value in ObjectHook definitions.

The issue was that Rollup's type definitions require the filter value
itself to accept undefined (not just be optional), which is necessary
for exactOptionalPropertyTypes compatibility.

Changes:
- resolveId: Add | undefined after filter object type
- load: Add | undefined after filter object type
- transform: Add | undefined after filter object type

This ensures Vite's Plugin interface correctly extends Rollup's
Plugin interface when exactOptionalPropertyTypes is enabled.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
…lity

The previous commit added `| undefined` to Rollup's filter object
definitions, which broke type compatibility with Rollup's Plugin interface.
This caused the CI check `ExpectExtends<RollupPlugin, Plugin>` to fail.

This commit reverts the filter object changes while keeping the
Vite-specific parameter fixes (ssr, scan) that resolve issue vitejs#20948.

Changes:
- Revert resolveId filter: { filter?: { id?: StringFilter<RegExp> } }
- Revert load filter: { filter?: { id?: StringFilter } }
- Revert transform filter: { filter?: { id?: StringFilter; code?: StringFilter } }
- Keep ssr?: boolean | undefined (fixes vitejs#20948)
- Keep scan?: boolean | undefined (internal parameter)

This maintains full type compatibility with Rollup while supporting
exactOptionalPropertyTypes for the spread pattern:
{ enforce: "pre", ...rollupPlugin() }

Fixes vitejs#20948

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@sapphi-red sapphi-red added the p2-edge-case Bug, but has workaround or limited in scope (priority) label Nov 5, 2025
Copy link
Member

@sapphi-red sapphi-red left a comment

Choose a reason for hiding this comment

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

Thank you!

@sapphi-red sapphi-red merged commit 2833c55 into vitejs:main Nov 5, 2025
17 checks passed
renovate bot added a commit to andrei-picus-tink/auto-renovate that referenced this pull request Nov 8, 2025
| datasource | package | from   | to    |
| ---------- | ------- | ------ | ----- |
| npm        | vite    | 7.1.10 | 7.2.2 |


## [v7.2.2](https://github.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#small-722-2025-11-07-small)

##### Bug Fixes

- revert "refactor: use fs.cpSync ([#21019](vitejs/vite#21019))" ([#21081](vitejs/vite#21081)) ([728c8ee](vitejs/vite@728c8ee))


## [v7.2.1](https://github.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#small-721-2025-11-06-small)

##### Bug Fixes

- **worker:** some worker asset was missing ([#21074](vitejs/vite#21074)) ([82d2d6c](vitejs/vite@82d2d6c))

##### Code Refactoring

- **build:** rename `indexOfMatchInSlice` to `findPreloadMarker` ([#21054](vitejs/vite#21054)) ([f83264f](vitejs/vite@f83264f))


## [v7.2.0](https://github.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#720-2025-11-05)

##### Bug Fixes

- **css:** fallback to sass when sass-embedded platform binary is missing ([#21002](vitejs/vite#21002)) ([b1fd616](vitejs/vite@b1fd616))
- **module-runner:** make `getBuiltins` response JSON serializable ([#21029](vitejs/vite#21029)) ([ad5b3bf](vitejs/vite@ad5b3bf))
- **types:** add undefined to optional properties for exactOptionalProperties type compatibility ([#21040](vitejs/vite#21040)) ([2833c55](vitejs/vite@2833c55))

##### Miscellaneous Chores

- **deps:** update rolldown-related dependencies ([#21047](vitejs/vite#21047)) ([e3a6a83](vitejs/vite@e3a6a83))


## [v7.1.12](https://github.com/vitejs/vite/releases/tag/v7.1.12)

Please refer to [CHANGELOG.md](https://github.com/vitejs/vite/blob/v7.1.12/packages/vite/CHANGELOG.md) for details.


## [v7.1.11](https://github.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#small-7111-2025-10-20-small)

##### Bug Fixes

- **dev:** trim trailing slash before `server.fs.deny` check ([#20968](vitejs/vite#20968)) ([f479cc5](vitejs/vite@f479cc5))

##### Miscellaneous Chores

- **deps:** update all non-major dependencies ([#20966](vitejs/vite#20966)) ([6fb41a2](vitejs/vite@6fb41a2))

##### Code Refactoring

- use subpath imports for types module reference ([#20921](vitejs/vite#20921)) ([d0094af](vitejs/vite@d0094af))

##### Build System

- remove cjs reference in files field ([#20945](vitejs/vite#20945)) ([ef411ce](vitejs/vite@ef411ce))
- remove hash from built filenames ([#20946](vitejs/vite#20946)) ([a817307](vitejs/vite@a817307))
renovate bot added a commit to andrei-picus-tink/auto-renovate that referenced this pull request Nov 8, 2025
| datasource | package | from   | to    |
| ---------- | ------- | ------ | ----- |
| npm        | vite    | 7.1.10 | 7.2.2 |


## [v7.2.2](https://github.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#small-722-2025-11-07-small)

##### Bug Fixes

- revert "refactor: use fs.cpSync ([#21019](vitejs/vite#21019))" ([#21081](vitejs/vite#21081)) ([728c8ee](vitejs/vite@728c8ee))


## [v7.2.1](https://github.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#small-721-2025-11-06-small)

##### Bug Fixes

- **worker:** some worker asset was missing ([#21074](vitejs/vite#21074)) ([82d2d6c](vitejs/vite@82d2d6c))

##### Code Refactoring

- **build:** rename `indexOfMatchInSlice` to `findPreloadMarker` ([#21054](vitejs/vite#21054)) ([f83264f](vitejs/vite@f83264f))


## [v7.2.0](https://github.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#720-2025-11-05)

##### Bug Fixes

- **css:** fallback to sass when sass-embedded platform binary is missing ([#21002](vitejs/vite#21002)) ([b1fd616](vitejs/vite@b1fd616))
- **module-runner:** make `getBuiltins` response JSON serializable ([#21029](vitejs/vite#21029)) ([ad5b3bf](vitejs/vite@ad5b3bf))
- **types:** add undefined to optional properties for exactOptionalProperties type compatibility ([#21040](vitejs/vite#21040)) ([2833c55](vitejs/vite@2833c55))

##### Miscellaneous Chores

- **deps:** update rolldown-related dependencies ([#21047](vitejs/vite#21047)) ([e3a6a83](vitejs/vite@e3a6a83))


## [v7.1.12](https://github.com/vitejs/vite/releases/tag/v7.1.12)

Please refer to [CHANGELOG.md](https://github.com/vitejs/vite/blob/v7.1.12/packages/vite/CHANGELOG.md) for details.


## [v7.1.11](https://github.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#small-7111-2025-10-20-small)

##### Bug Fixes

- **dev:** trim trailing slash before `server.fs.deny` check ([#20968](vitejs/vite#20968)) ([f479cc5](vitejs/vite@f479cc5))

##### Miscellaneous Chores

- **deps:** update all non-major dependencies ([#20966](vitejs/vite#20966)) ([6fb41a2](vitejs/vite@6fb41a2))

##### Code Refactoring

- use subpath imports for types module reference ([#20921](vitejs/vite#20921)) ([d0094af](vitejs/vite@d0094af))

##### Build System

- remove cjs reference in files field ([#20945](vitejs/vite#20945)) ([ef411ce](vitejs/vite@ef411ce))
- remove hash from built filenames ([#20946](vitejs/vite#20946)) ([a817307](vitejs/vite@a817307))
renovate bot added a commit to andrei-picus-tink/auto-renovate that referenced this pull request Nov 9, 2025
| datasource | package | from   | to    |
| ---------- | ------- | ------ | ----- |
| npm        | vite    | 7.1.10 | 7.2.2 |


## [v7.2.2](https://github.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#small-722-2025-11-07-small)

##### Bug Fixes

- revert "refactor: use fs.cpSync ([#21019](vitejs/vite#21019))" ([#21081](vitejs/vite#21081)) ([728c8ee](vitejs/vite@728c8ee))


## [v7.2.1](https://github.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#small-721-2025-11-06-small)

##### Bug Fixes

- **worker:** some worker asset was missing ([#21074](vitejs/vite#21074)) ([82d2d6c](vitejs/vite@82d2d6c))

##### Code Refactoring

- **build:** rename `indexOfMatchInSlice` to `findPreloadMarker` ([#21054](vitejs/vite#21054)) ([f83264f](vitejs/vite@f83264f))


## [v7.2.0](https://github.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#720-2025-11-05)

##### Bug Fixes

- **css:** fallback to sass when sass-embedded platform binary is missing ([#21002](vitejs/vite#21002)) ([b1fd616](vitejs/vite@b1fd616))
- **module-runner:** make `getBuiltins` response JSON serializable ([#21029](vitejs/vite#21029)) ([ad5b3bf](vitejs/vite@ad5b3bf))
- **types:** add undefined to optional properties for exactOptionalProperties type compatibility ([#21040](vitejs/vite#21040)) ([2833c55](vitejs/vite@2833c55))

##### Miscellaneous Chores

- **deps:** update rolldown-related dependencies ([#21047](vitejs/vite#21047)) ([e3a6a83](vitejs/vite@e3a6a83))


## [v7.1.12](https://github.com/vitejs/vite/releases/tag/v7.1.12)

Please refer to [CHANGELOG.md](https://github.com/vitejs/vite/blob/v7.1.12/packages/vite/CHANGELOG.md) for details.


## [v7.1.11](https://github.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#small-7111-2025-10-20-small)

##### Bug Fixes

- **dev:** trim trailing slash before `server.fs.deny` check ([#20968](vitejs/vite#20968)) ([f479cc5](vitejs/vite@f479cc5))

##### Miscellaneous Chores

- **deps:** update all non-major dependencies ([#20966](vitejs/vite#20966)) ([6fb41a2](vitejs/vite@6fb41a2))

##### Code Refactoring

- use subpath imports for types module reference ([#20921](vitejs/vite#20921)) ([d0094af](vitejs/vite@d0094af))

##### Build System

- remove cjs reference in files field ([#20945](vitejs/vite#20945)) ([ef411ce](vitejs/vite@ef411ce))
- remove hash from built filenames ([#20946](vitejs/vite#20946)) ([a817307](vitejs/vite@a817307))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

p2-edge-case Bug, but has workaround or limited in scope (priority)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

regression: Plugin type no longer compatible with rollup

2 participants