diff --git a/packages/next/client/router.ts b/packages/next/client/router.ts index 0506802441ad4..f8681b9885312 100644 --- a/packages/next/client/router.ts +++ b/packages/next/client/router.ts @@ -17,6 +17,14 @@ export { Router, NextRouter } export type SingletonRouter = SingletonRouterBase & NextRouter +export type RouterEvent = + | 'routeChangeStart' + | 'beforeHistoryChange' + | 'routeChangeComplete' + | 'routeChangeError' + | 'hashChangeStart' + | 'hashChangeComplete' + const singletonRouter: SingletonRouterBase = { router: null, // holds the actual router instance readyCallbacks: [], @@ -44,7 +52,7 @@ const urlPropertyFields = [ 'isPreview', 'isLocaleDomain', ] -const routerEvents = [ +const routerEvents: RouterEvent[] = [ 'routeChangeStart', 'beforeHistoryChange', 'routeChangeComplete', @@ -89,9 +97,9 @@ coreMethodFields.forEach((field: string) => { } }) -routerEvents.forEach((event: string) => { +routerEvents.forEach((event) => { singletonRouter.ready(() => { - Router.events.on(event, (...args) => { + Router.events.on(event as any, (...args: any[]) => { const eventField = `on${event.charAt(0).toUpperCase()}${event.substring( 1 )}` diff --git a/packages/next/next-server/lib/mitt.ts b/packages/next/next-server/lib/mitt.ts index e7c57c33b6e6c..2452227f0a1fb 100644 --- a/packages/next/next-server/lib/mitt.ts +++ b/packages/next/next-server/lib/mitt.ts @@ -16,10 +16,13 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI type Handler = (...evts: any[]) => void -export type MittEmitter = { - on(type: string, handler: Handler): void - off(type: string, handler: Handler): void - emit(type: string, ...evts: any[]): void +export type MittEmitter< + Type extends string = string, + Func extends Handler = Handler +> = { + on(type: Type, handler: Func): void + off(type: Type, handler: Func): void + emit(type: Type, ...evts: any[]): void } export default function mitt(): MittEmitter { diff --git a/packages/next/next-server/lib/router/router.ts b/packages/next/next-server/lib/router/router.ts index e9502affb3ba2..c0df8d8285f95 100644 --- a/packages/next/next-server/lib/router/router.ts +++ b/packages/next/next-server/lib/router/router.ts @@ -13,6 +13,7 @@ import { isAssetError, markAssetError, } from '../../../client/route-loader' +import { RouterEvent } from '../../../client/router' import { DomainLocales } from '../../server/config' import { denormalizePagePath } from '../../server/denormalize-page-path' import { normalizeLocalePath } from '../i18n/normalize-locale-path' @@ -424,6 +425,19 @@ type ComponentLoadCancel = (() => void) | null type HistoryMethod = 'replaceState' | 'pushState' +type RouterEventEmitter = MittEmitter< + Exclude, + (url: string, routeProps: { shallow: boolean }) => void +> & + MittEmitter< + 'routeChangeError', + ( + err: Error & { cancelled: boolean }, + url: string, + routeProps: { shallow: boolean } + ) => void + > + const manualScrollRestoration = process.env.__NEXT_SCROLL_RESTORATION && typeof window !== 'undefined' && @@ -504,7 +518,7 @@ export default class Router implements BaseRouter { clc: ComponentLoadCancel pageLoader: any _bps: BeforePopStateCallback | undefined - events: MittEmitter + events: RouterEventEmitter = mitt() _wrapApp: (App: AppComponent) => any isSsr: boolean isFallback: boolean @@ -520,7 +534,7 @@ export default class Router implements BaseRouter { private _idx: number = 0 - static events: MittEmitter = mitt() + static events: RouterEventEmitter = mitt() constructor( pathname: string,