#Can we customize the page props helper types?

1 messages · Page 1 of 1 (latest)

timber marsh
#
export default async function Page(props: PageProps<'/[locale]/blog'>) {
  const { locale } = await props.params

  return <h1>Locale: {locale}</h1>
}

Locale should be a type of locale

locale: 'en' | 'zh-TW' | 'zh-CN'
vivid houndBOT
#

Hi @timber marsh. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

Based on the provided knowledge sources, the built-in PageProps helper in Next.js infers the params type from your route structure, but it does not automatically narrow dynamic parameters (like locale) to a specific union type such as 'en' | 'zh-TW' | 'zh-CN'. By default, params are typed as string for dynamic segments, even if you know the possible values are more restricted. For example:

export default async function Page(props: PageProps<'/[locale]/blog'>) {
  const { locale } = await props.params // locale: string
  // ...
}

See reference

If you want to enforce a stricter type for locale, you need to manually narrow the type within your component. One recommended approach is to use a type guard or assertion after extracting the param, as shown in community discussions:

function validateLocale(locale: unknown): asserts locale is 'en' | 'zh-TW' | 'zh-CN' {
  if (locale === 'en' || locale === 'zh-TW' || locale === 'zh-CN') return
  throw new Error('Invalid locale')
}

export default async function Page(props: PageProps<'/[locale]/blog'>) {
  const { locale } = await props.params
  validateLocale(locale)
  // Now locale is 'en' | 'zh-TW' | 'zh-CN'
  return <h1>Locale: {locale}</h1>
}

See related discussion

Currently, there is no documented way to customize the PageProps helper itself to infer a union type for params directly from your route. You must handle the type narrowing in your code.

#

Summary:
You cannot customize the PageProps helper to infer a union type for params. You should use a type guard or assertion to narrow the type after extracting it from params, as shown above.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: