Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add typing to router events #25679

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions packages/next/client/router.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
/* global window */
import React from 'react'
import Router, { NextRouter } from '../next-server/lib/router/router'
import Router, {
NextRouter,
RouterEvents,
} from '../next-server/lib/router/router'
import { RouterContext } from '../next-server/lib/router-context'

type ClassArguments<T> = T extends new (...args: infer U) => any ? U : any
Expand Down Expand Up @@ -44,7 +47,7 @@ const urlPropertyFields = [
'isPreview',
'isLocaleDomain',
]
const routerEvents = [
const routerEvents: RouterEvents[] = [
'routeChangeStart',
'beforeHistoryChange',
'routeChangeComplete',
Expand Down Expand Up @@ -89,7 +92,7 @@ coreMethodFields.forEach((field: string) => {
}
})

routerEvents.forEach((event: string) => {
routerEvents.forEach((event) => {
singletonRouter.ready(() => {
Router.events.on(event, (...args) => {
const eventField = `on${event.charAt(0).toUpperCase()}${event.substring(
Expand Down
21 changes: 12 additions & 9 deletions packages/next/next-server/lib/mitt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,29 +14,32 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
// It's been edited for the needs of this script
// See the LICENSE at the top of the file

type Handler = (...evts: any[]) => void
type Handler<Event = any> = (...evts: Event[]) => 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<EventType extends string = string, Event = any> = {
on(type: EventType, handler: Handler<Event>): void
off(type: EventType, handler: Handler<Event>): void
emit(type: EventType, ...evts: Event[]): void
}

export default function mitt(): MittEmitter {
export default function mitt<
EventType extends string = string,
Event = any
>(): MittEmitter<EventType, Event> {
const all: { [s: string]: Handler[] } = Object.create(null)

return {
on(type: string, handler: Handler) {
on(type: EventType, handler: Handler<Event>) {
;(all[type] || (all[type] = [])).push(handler)
},

off(type: string, handler: Handler) {
off(type: EventType, handler: Handler<Event>) {
if (all[type]) {
all[type].splice(all[type].indexOf(handler) >>> 0, 1)
}
},

emit(type: string, ...evts: any[]) {
emit(type: EventType, ...evts: Event[]) {
// eslint-disable-next-line array-callback-return
;(all[type] || []).slice().map((handler: Handler) => {
handler(...evts)
Expand Down
12 changes: 10 additions & 2 deletions packages/next/next-server/lib/router/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,14 @@ type ComponentLoadCancel = (() => void) | null

type HistoryMethod = 'replaceState' | 'pushState'

export type RouterEvents =
| 'routeChangeStart'
| 'routeChangeComplete'
| 'routeChangeError'
| 'beforeHistoryChange'
| 'hashChangeStart'
| 'hashChangeComplete'

const manualScrollRestoration =
process.env.__NEXT_SCROLL_RESTORATION &&
typeof window !== 'undefined' &&
Expand Down Expand Up @@ -522,7 +530,7 @@ export default class Router implements BaseRouter {
clc: ComponentLoadCancel
pageLoader: any
_bps: BeforePopStateCallback | undefined
events: MittEmitter
events: MittEmitter<RouterEvents>
_wrapApp: (App: AppComponent) => any
isSsr: boolean
isFallback: boolean
Expand All @@ -538,7 +546,7 @@ export default class Router implements BaseRouter {

private _idx: number = 0

static events: MittEmitter = mitt()
static events: MittEmitter<RouterEvents> = mitt()

constructor(
pathname: string,
Expand Down
4 changes: 2 additions & 2 deletions test/integration/typescript/components/router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ import Router, { withRouter } from 'next/router'

export default withRouter(({ router }) => {
React.useEffect(() => {
Router.events.on('event', () => {})
Router.events.on('routeChangeStart', () => {})
Router.prefetch('/page')
Router.push
Router.back
Router.reload

router.events.on('event', () => {})
router.events.on('routeChangeStart', () => {})
router.prefetch('/page')
router.push
router.back
Expand Down