diff --git a/docs/guide/api-plugin.md b/docs/guide/api-plugin.md
index 8d81c9c0a21e1d..3bfcc65c77c322 100644
--- a/docs/guide/api-plugin.md
+++ b/docs/guide/api-plugin.md
@@ -609,9 +609,9 @@ It is possible to type custom events by extending the `CustomEventMap` interface
```ts
// events.d.ts
-import 'vite/types/customEvent'
+import 'vite/types/custom-event'
-declare module 'vite/types/customEvent' {
+declare module 'vite/types/custom-event' {
interface CustomEventMap {
'custom:foo': { msg: string }
// 'event-key': payload
diff --git a/packages/vite/client.d.ts b/packages/vite/client.d.ts
index 28cad860982874..ee418786a9c079 100644
--- a/packages/vite/client.d.ts
+++ b/packages/vite/client.d.ts
@@ -1,4 +1,4 @@
-///
+///
// CSS modules
type CSSModuleClasses = { readonly [key: string]: string }
diff --git a/packages/vite/package.json b/packages/vite/package.json
index 2bd0d3d0d354c0..e647c21bdcb8aa 100644
--- a/packages/vite/package.json
+++ b/packages/vite/package.json
@@ -38,7 +38,7 @@
"dist",
"client.d.ts",
"index.cjs",
- "types"
+ "types/*.d.ts"
],
"engines": {
"node": "^18.0.0 || >=20.0.0"
diff --git a/packages/vite/src/client/client.ts b/packages/vite/src/client/client.ts
index b909c1328a9a3b..f05893a8f88739 100644
--- a/packages/vite/src/client/client.ts
+++ b/packages/vite/src/client/client.ts
@@ -1,6 +1,6 @@
-import type { ErrorPayload, HMRPayload, Update } from 'types/hmrPayload'
+import type { ErrorPayload, HMRPayload, Update } from 'types/hmr-payload'
import type { ModuleNamespace, ViteHotContext } from 'types/hot'
-import type { InferCustomEventPayload } from 'types/customEvent'
+import type { InferCustomEventPayload } from 'types/custom-event'
import { ErrorOverlay, overlayId } from './overlay'
import '@vite/env'
diff --git a/packages/vite/src/client/overlay.ts b/packages/vite/src/client/overlay.ts
index 508eaf7e05bc9e..c795ee976df228 100644
--- a/packages/vite/src/client/overlay.ts
+++ b/packages/vite/src/client/overlay.ts
@@ -1,4 +1,4 @@
-import type { ErrorPayload } from 'types/hmrPayload'
+import type { ErrorPayload } from 'types/hmr-payload'
// injected by the hmr plugin when served
declare const __BASE__: string
diff --git a/packages/vite/src/node/__tests__/plugins/importGlob/__snapshots__/fixture.test.ts.snap b/packages/vite/src/node/__tests__/plugins/importGlob/__snapshots__/fixture.test.ts.snap
index 983aa3072a2013..51d89f91e83280 100644
--- a/packages/vite/src/node/__tests__/plugins/importGlob/__snapshots__/fixture.test.ts.snap
+++ b/packages/vite/src/node/__tests__/plugins/importGlob/__snapshots__/fixture.test.ts.snap
@@ -1,7 +1,7 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`fixture > transform 1`] = `
-"import * as __vite_glob_1_0 from \\"./modules/a.ts\\";import * as __vite_glob_1_1 from \\"./modules/b.ts\\";import * as __vite_glob_1_2 from \\"./modules/index.ts\\";import { name as __vite_glob_3_0 } from \\"./modules/a.ts\\";import { name as __vite_glob_3_1 } from \\"./modules/b.ts\\";import { name as __vite_glob_3_2 } from \\"./modules/index.ts\\";import { default as __vite_glob_5_0 } from \\"./modules/a.ts?raw\\";import { default as __vite_glob_5_1 } from \\"./modules/b.ts?raw\\";import \\"types/importMeta\\";
+"import * as __vite_glob_1_0 from \\"./modules/a.ts\\";import * as __vite_glob_1_1 from \\"./modules/b.ts\\";import * as __vite_glob_1_2 from \\"./modules/index.ts\\";import { name as __vite_glob_3_0 } from \\"./modules/a.ts\\";import { name as __vite_glob_3_1 } from \\"./modules/b.ts\\";import { name as __vite_glob_3_2 } from \\"./modules/index.ts\\";import { default as __vite_glob_5_0 } from \\"./modules/a.ts?raw\\";import { default as __vite_glob_5_1 } from \\"./modules/b.ts?raw\\";import \\"types/import-meta\\";
export const basic = /* #__PURE__ */ Object.assign({\\"./modules/a.ts\\": () => import(\\"./modules/a.ts\\"),\\"./modules/b.ts\\": () => import(\\"./modules/b.ts\\"),\\"./modules/index.ts\\": () => import(\\"./modules/index.ts\\")});
export const basicEager = /* #__PURE__ */ Object.assign({\\"./modules/a.ts\\": __vite_glob_1_0,\\"./modules/b.ts\\": __vite_glob_1_1,\\"./modules/index.ts\\": __vite_glob_1_2
@@ -39,7 +39,7 @@ export const customQueryObject = /* #__PURE__ */ Object.assign({\\"./sibling.ts\
export const parent = /* #__PURE__ */ Object.assign({
});
-export const rootMixedRelative = /* #__PURE__ */ Object.assign({\\"/css.spec.ts\\": () => import(\\"../../css.spec.ts?url\\").then(m => m[\\"default\\"]),\\"/define.spec.ts\\": () => import(\\"../../define.spec.ts?url\\").then(m => m[\\"default\\"]),\\"/esbuild.spec.ts\\": () => import(\\"../../esbuild.spec.ts?url\\").then(m => m[\\"default\\"]),\\"/import.spec.ts\\": () => import(\\"../../import.spec.ts?url\\").then(m => m[\\"default\\"]),\\"/importGlob/fixture-b/a.ts\\": () => import(\\"../fixture-b/a.ts?url\\").then(m => m[\\"default\\"]),\\"/importGlob/fixture-b/b.ts\\": () => import(\\"../fixture-b/b.ts?url\\").then(m => m[\\"default\\"]),\\"/importGlob/fixture-b/index.ts\\": () => import(\\"../fixture-b/index.ts?url\\").then(m => m[\\"default\\"])
+export const rootMixedRelative = /* #__PURE__ */ Object.assign({\\"/css.spec.ts\\": () => import(\\"../../css.spec.ts?url\\").then(m => m[\\"default\\"]),\\"/define.spec.ts\\": () => import(\\"../../define.spec.ts?url\\").then(m => m[\\"default\\"]),\\"/esbuild.spec.ts\\": () => import(\\"../../esbuild.spec.ts?url\\").then(m => m[\\"default\\"]),\\"/import.spec.ts\\": () => import(\\"../../import.spec.ts?url\\").then(m => m[\\"default\\"]),\\"/import-glob/fixture-b/a.ts\\": () => import(\\"../fixture-b/a.ts?url\\").then(m => m[\\"default\\"]),\\"/import-glob/fixture-b/b.ts\\": () => import(\\"../fixture-b/b.ts?url\\").then(m => m[\\"default\\"]),\\"/import-glob/fixture-b/index.ts\\": () => import(\\"../fixture-b/index.ts?url\\").then(m => m[\\"default\\"])
});
@@ -55,7 +55,7 @@ export const cleverCwd2 = /* #__PURE__ */ Object.assign({\\"./modules/a.ts\\": (
`;
exports[`fixture > transform with restoreQueryExtension 1`] = `
-"import * as __vite_glob_1_0 from \\"./modules/a.ts\\";import * as __vite_glob_1_1 from \\"./modules/b.ts\\";import * as __vite_glob_1_2 from \\"./modules/index.ts\\";import { name as __vite_glob_3_0 } from \\"./modules/a.ts\\";import { name as __vite_glob_3_1 } from \\"./modules/b.ts\\";import { name as __vite_glob_3_2 } from \\"./modules/index.ts\\";import { default as __vite_glob_5_0 } from \\"./modules/a.ts?raw\\";import { default as __vite_glob_5_1 } from \\"./modules/b.ts?raw\\";import \\"types/importMeta\\";
+"import * as __vite_glob_1_0 from \\"./modules/a.ts\\";import * as __vite_glob_1_1 from \\"./modules/b.ts\\";import * as __vite_glob_1_2 from \\"./modules/index.ts\\";import { name as __vite_glob_3_0 } from \\"./modules/a.ts\\";import { name as __vite_glob_3_1 } from \\"./modules/b.ts\\";import { name as __vite_glob_3_2 } from \\"./modules/index.ts\\";import { default as __vite_glob_5_0 } from \\"./modules/a.ts?raw\\";import { default as __vite_glob_5_1 } from \\"./modules/b.ts?raw\\";import \\"types/import-meta\\";
export const basic = /* #__PURE__ */ Object.assign({\\"./modules/a.ts\\": () => import(\\"./modules/a.ts\\"),\\"./modules/b.ts\\": () => import(\\"./modules/b.ts\\"),\\"./modules/index.ts\\": () => import(\\"./modules/index.ts\\")});
export const basicEager = /* #__PURE__ */ Object.assign({\\"./modules/a.ts\\": __vite_glob_1_0,\\"./modules/b.ts\\": __vite_glob_1_1,\\"./modules/index.ts\\": __vite_glob_1_2
@@ -93,7 +93,7 @@ export const customQueryObject = /* #__PURE__ */ Object.assign({\\"./sibling.ts\
export const parent = /* #__PURE__ */ Object.assign({
});
-export const rootMixedRelative = /* #__PURE__ */ Object.assign({\\"/css.spec.ts\\": () => import(\\"../../css.spec.ts?url&lang.ts\\").then(m => m[\\"default\\"]),\\"/define.spec.ts\\": () => import(\\"../../define.spec.ts?url&lang.ts\\").then(m => m[\\"default\\"]),\\"/esbuild.spec.ts\\": () => import(\\"../../esbuild.spec.ts?url&lang.ts\\").then(m => m[\\"default\\"]),\\"/import.spec.ts\\": () => import(\\"../../import.spec.ts?url&lang.ts\\").then(m => m[\\"default\\"]),\\"/importGlob/fixture-b/a.ts\\": () => import(\\"../fixture-b/a.ts?url&lang.ts\\").then(m => m[\\"default\\"]),\\"/importGlob/fixture-b/b.ts\\": () => import(\\"../fixture-b/b.ts?url&lang.ts\\").then(m => m[\\"default\\"]),\\"/importGlob/fixture-b/index.ts\\": () => import(\\"../fixture-b/index.ts?url&lang.ts\\").then(m => m[\\"default\\"])
+export const rootMixedRelative = /* #__PURE__ */ Object.assign({\\"/css.spec.ts\\": () => import(\\"../../css.spec.ts?url&lang.ts\\").then(m => m[\\"default\\"]),\\"/define.spec.ts\\": () => import(\\"../../define.spec.ts?url&lang.ts\\").then(m => m[\\"default\\"]),\\"/esbuild.spec.ts\\": () => import(\\"../../esbuild.spec.ts?url&lang.ts\\").then(m => m[\\"default\\"]),\\"/import.spec.ts\\": () => import(\\"../../import.spec.ts?url&lang.ts\\").then(m => m[\\"default\\"]),\\"/import-glob/fixture-b/a.ts\\": () => import(\\"../fixture-b/a.ts?url&lang.ts\\").then(m => m[\\"default\\"]),\\"/import-glob/fixture-b/b.ts\\": () => import(\\"../fixture-b/b.ts?url&lang.ts\\").then(m => m[\\"default\\"]),\\"/import-glob/fixture-b/index.ts\\": () => import(\\"../fixture-b/index.ts?url&lang.ts\\").then(m => m[\\"default\\"])
});
diff --git a/packages/vite/src/node/__tests__/plugins/importGlob/fixture-a/index.ts b/packages/vite/src/node/__tests__/plugins/importGlob/fixture-a/index.ts
index 49b203c3ae093f..e24568839983ba 100644
--- a/packages/vite/src/node/__tests__/plugins/importGlob/fixture-a/index.ts
+++ b/packages/vite/src/node/__tests__/plugins/importGlob/fixture-a/index.ts
@@ -1,4 +1,4 @@
-import 'types/importMeta'
+import 'types/import-meta'
export interface ModuleType {
name: string
diff --git a/packages/vite/src/node/index.ts b/packages/vite/src/node/index.ts
index 0ab0747fade26c..3e2a75fecf1e15 100644
--- a/packages/vite/src/node/index.ts
+++ b/packages/vite/src/node/index.ts
@@ -110,18 +110,18 @@ export type {
CustomPayload,
PrunePayload,
ErrorPayload,
-} from 'types/hmrPayload'
+} from 'types/hmr-payload'
export type {
CustomEventMap,
InferCustomEventPayload,
InvalidatePayload,
-} from 'types/customEvent'
+} from 'types/custom-event'
export type {
ImportGlobFunction,
ImportGlobOptions,
GeneralImportGlobOptions,
KnownAsTypeMap,
-} from 'types/importGlob'
+} from 'types/import-glob'
export type { ChunkMetadata } from 'types/metadata'
// dep types
diff --git a/packages/vite/src/node/plugins/dynamicImportVars.ts b/packages/vite/src/node/plugins/dynamicImportVars.ts
index f4956046c219ff..e8489598a70395 100644
--- a/packages/vite/src/node/plugins/dynamicImportVars.ts
+++ b/packages/vite/src/node/plugins/dynamicImportVars.ts
@@ -4,7 +4,7 @@ import { init, parse as parseImports } from 'es-module-lexer'
import type { ImportSpecifier } from 'es-module-lexer'
import { parse as parseJS } from 'acorn'
import { dynamicImportToGlob } from '@rollup/plugin-dynamic-import-vars'
-import type { KnownAsTypeMap } from 'types/importGlob'
+import type { KnownAsTypeMap } from 'types/import-glob'
import type { Plugin } from '../plugin'
import type { ResolvedConfig } from '../config'
import { CLIENT_ENTRY } from '../constants'
diff --git a/packages/vite/src/node/plugins/importMetaGlob.ts b/packages/vite/src/node/plugins/importMetaGlob.ts
index c76ab9f495196d..bd4ba728be8a3b 100644
--- a/packages/vite/src/node/plugins/importMetaGlob.ts
+++ b/packages/vite/src/node/plugins/importMetaGlob.ts
@@ -18,7 +18,7 @@ import { findNodeAt } from 'acorn-walk'
import MagicString from 'magic-string'
import fg from 'fast-glob'
import { stringifyQuery } from 'ufo'
-import type { GeneralImportGlobOptions } from 'types/importGlob'
+import type { GeneralImportGlobOptions } from 'types/import-glob'
import type { Plugin } from '../plugin'
import type { ViteDevServer } from '../server'
import type { ModuleNode } from '../server/moduleGraph'
diff --git a/packages/vite/src/node/server/hmr.ts b/packages/vite/src/node/server/hmr.ts
index f708b1114ed3cd..29649441e75557 100644
--- a/packages/vite/src/node/server/hmr.ts
+++ b/packages/vite/src/node/server/hmr.ts
@@ -2,7 +2,7 @@ import fsp from 'node:fs/promises'
import path from 'node:path'
import type { Server } from 'node:http'
import colors from 'picocolors'
-import type { Update } from 'types/hmrPayload'
+import type { Update } from 'types/hmr-payload'
import type { RollupError } from 'rollup'
import { CLIENT_DIR } from '../constants'
import {
diff --git a/packages/vite/src/node/server/index.ts b/packages/vite/src/node/server/index.ts
index 7510e740a7bfad..1973510818aaba 100644
--- a/packages/vite/src/node/server/index.ts
+++ b/packages/vite/src/node/server/index.ts
@@ -12,7 +12,7 @@ import launchEditorMiddleware from 'launch-editor-middleware'
import type { SourceMap } from 'rollup'
import picomatch from 'picomatch'
import type { Matcher } from 'picomatch'
-import type { InvalidatePayload } from 'types/customEvent'
+import type { InvalidatePayload } from 'types/custom-event'
import type { CommonServerOptions } from '../http'
import {
httpServerStart,
diff --git a/packages/vite/src/node/server/middlewares/error.ts b/packages/vite/src/node/server/middlewares/error.ts
index 966d1663749ba2..c47c0ce497331d 100644
--- a/packages/vite/src/node/server/middlewares/error.ts
+++ b/packages/vite/src/node/server/middlewares/error.ts
@@ -2,7 +2,7 @@ import colors from 'picocolors'
import type { RollupError } from 'rollup'
import type { Connect } from 'dep-types/connect'
import strip from 'strip-ansi'
-import type { ErrorPayload } from 'types/hmrPayload'
+import type { ErrorPayload } from 'types/hmr-payload'
import { pad } from '../../utils'
import type { ViteDevServer } from '../..'
diff --git a/packages/vite/src/node/server/ws.ts b/packages/vite/src/node/server/ws.ts
index 7df59370f9e1d8..ae7114c68ec8a9 100644
--- a/packages/vite/src/node/server/ws.ts
+++ b/packages/vite/src/node/server/ws.ts
@@ -9,8 +9,8 @@ import colors from 'picocolors'
import type { WebSocket as WebSocketRaw } from 'ws'
import { WebSocketServer as WebSocketServerRaw_ } from 'ws'
import type { WebSocket as WebSocketTypes } from 'dep-types/ws'
-import type { CustomPayload, ErrorPayload, HMRPayload } from 'types/hmrPayload'
-import type { InferCustomEventPayload } from 'types/customEvent'
+import type { CustomPayload, ErrorPayload, HMRPayload } from 'types/hmr-payload'
+import type { InferCustomEventPayload } from 'types/custom-event'
import type { ResolvedConfig } from '..'
import { isObject } from '../utils'
diff --git a/packages/vite/types/README.md b/packages/vite/types/README.md
new file mode 100644
index 00000000000000..28ba38a5517061
--- /dev/null
+++ b/packages/vite/types/README.md
@@ -0,0 +1 @@
+Custom types that users can extend in their projects. Make sure the files are named using kebab-case due to a TypeScript bug: https://github.com/microsoft/TypeScript/issues/45096.
diff --git a/packages/vite/types/customEvent.d.ts b/packages/vite/types/custom-event.d.ts
similarity index 97%
rename from packages/vite/types/customEvent.d.ts
rename to packages/vite/types/custom-event.d.ts
index a72c1b85fc1ad0..ad5623e3f30e46 100644
--- a/packages/vite/types/customEvent.d.ts
+++ b/packages/vite/types/custom-event.d.ts
@@ -3,7 +3,7 @@ import type {
FullReloadPayload,
PrunePayload,
UpdatePayload,
-} from './hmrPayload'
+} from './hmr-payload'
export interface CustomEventMap {
'vite:beforeUpdate': UpdatePayload
diff --git a/packages/vite/types/hmrPayload.d.ts b/packages/vite/types/hmr-payload.d.ts
similarity index 100%
rename from packages/vite/types/hmrPayload.d.ts
rename to packages/vite/types/hmr-payload.d.ts
diff --git a/packages/vite/types/hot.d.ts b/packages/vite/types/hot.d.ts
index 5e8a450151606b..9427b5842c054f 100644
--- a/packages/vite/types/hot.d.ts
+++ b/packages/vite/types/hot.d.ts
@@ -1,4 +1,4 @@
-import type { InferCustomEventPayload } from './customEvent'
+import type { InferCustomEventPayload } from './custom-event'
export type ModuleNamespace = Record & {
[Symbol.toStringTag]: 'Module'
diff --git a/packages/vite/types/importGlob.d.ts b/packages/vite/types/import-glob.d.ts
similarity index 100%
rename from packages/vite/types/importGlob.d.ts
rename to packages/vite/types/import-glob.d.ts
diff --git a/packages/vite/types/importMeta.d.ts b/packages/vite/types/import-meta.d.ts
similarity index 90%
rename from packages/vite/types/importMeta.d.ts
rename to packages/vite/types/import-meta.d.ts
index bd4418379951b3..422c1a90cd4dda 100644
--- a/packages/vite/types/importMeta.d.ts
+++ b/packages/vite/types/import-meta.d.ts
@@ -18,5 +18,5 @@ interface ImportMeta {
readonly env: ImportMetaEnv
- glob: import('./importGlob').ImportGlobFunction
+ glob: import('./import-glob').ImportGlobFunction
}
diff --git a/playground/hmr/event.d.ts b/playground/hmr/event.d.ts
index 151a9cc3b861cd..2352b77e32a732 100644
--- a/playground/hmr/event.d.ts
+++ b/playground/hmr/event.d.ts
@@ -1,6 +1,6 @@
-import 'vite/types/customEvent'
+import 'vite/types/custom-event'
-declare module 'vite/types/customEvent' {
+declare module 'vite/types/custom-event' {
interface CustomEventMap {
'custom:foo': { msg: string }
'custom:remote-add': { a: number; b: number }