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

feat!: Revamp augmented types and add support for typed Locale #1495

Merged
merged 21 commits into from
Nov 1, 2024

Conversation

amannn
Copy link
Owner

@amannn amannn commented Oct 31, 2024

// global.d.ts

import {routing} from '@/i18n/routing';
import {formats} from '@/i18n/request';
import en from './messages/en.json';

declare module 'next-intl' {
  interface AppConfig {
    Locale: (typeof routing.locales)[number];
    Formats: typeof formats;
    Messages: typeof en;
  }
}

Note that all entries in AppConfig are optional and can be added as necessary—if at all.

Features

  • Adds support for strictly-typing the locale across all APIs from next-intl.
  • Adds import {Locale} from 'next-intl'; as a convenience API to be used wherever a locale is passed around (example).
  • Add hasLocale(locales: Array<Locale>, candidate: string): candidate is Locale API for simplified checking of whether a locale matches a given list of locales while also correctly narrowing the type (example).
  • Adds a new import {Messages} from 'next-intl; type that corresponds to the Messages you've provided in AppConfig (probably rarely needed).

Breaking changes

  • Gets rid of the global types IntlMessages and IntlFormats in favor of a more general AppConfig that is scoped to next-intl.

Proposed docs


Resolves #1377

Copy link

vercel bot commented Oct 31, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
next-intl-docs ✅ Ready (Inspect) Visit Preview 💬 Add feedback Nov 1, 2024 8:49am
next-intl-example-app-router ✅ Ready (Inspect) Visit Preview 💬 Add feedback Nov 1, 2024 8:49am
next-intl-example-app-router-without-i18n-routing ✅ Ready (Inspect) Visit Preview 💬 Add feedback Nov 1, 2024 8:49am

@amannn
Copy link
Owner Author

amannn commented Oct 31, 2024

Hey @dBianchii, as part of the upcoming v4 release of next-intl, I revamped the type augmentation a bit. The new API gets rid of previously needed globals and now also provides opt-in type-safety for locale.

Since this is closely related to PR #1346 that you've worked on, I was wondering if you're curious to have a look? The PR description has the relevant details. If you're up for it, would be cool if you could have a look at the updated TypeScript docs page to see if this sounds reasonable to you.

I was honestly a bit surprised that the strict typing of locale (along with the introduction of the Locale type) has some interesting implications, but seems to work really nicely if used consistently in apps :). I was also able to simplify i18n/request.ts a bit with a newly introduced hasLocale util (prev, now).

The PR is pretty much ready to go from my perspective, but I need to give it another look tomorrow—my head is already spinning a bit from the type wrestling today 😄.

Would be curious if you have an opinion here!

@chertik77
Copy link

I'm waiting for that so much, great pr! 🙂

@dBianchii
Copy link
Contributor

Hi @amannn, awesome! I'll try to take a look either today or tomorrow. Can't really promise it as I am quite busy, so please don't wait for me for release.
By what I understand it's a more local type configuration only for next-intl instead of a declare global, as well as a new interface for type-safe Locales. In my project I was already setting a export const locales = ["en", "pt-BR"] as const somewhere and that was enough to get the types for it anywhere I needed, so I'll have to see how you decided to implement this and provide feedback when possible.

Thanks!

@amannn
Copy link
Owner Author

amannn commented Nov 1, 2024

@dBianchii No worries, only if you have the time! The feature will be part of the upcoming v4 version, that will first have to go through a beta/RC phase—so no stress at all.

In my project I was already setting a export const locales = ["en", "pt-BR"] as const somewhere and that was enough to get the types for it anywhere I needed, so I'll have to see how you decided to implement this and provide feedback when possible.

Yep, I also did something similar like this before in projects:

export const locales = ["en", "pt-BR"] as const;
export type Locale = (typeof locales)[number];

(or based on routing.locales)

This can be used in userland-code, but the difference now is that next-intl will consider the Locale type where relevant (e.g. when returned from useLocale, when using <Link locale={…} />, etc.). It's a small quality-of-life improvement in those cases, but overall I think a cool aspect is that this nudges users to use the now-exported import {Locale} from 'next-intl' where relevant, instead of defaulting to string, generally enhancing the type-safety across your project.

Also, you can start with Locale defaulting to string, and later switch to a strictly-typed Locale if desired. I'm now suggesting the Locale type in the getting started with i18n routing docs, just as a quick hint that Locale exists. It's in fact not quite necessary there since the incoming locale is validated, it's more about providing some awareness for it in a subtle way. If you start out with using Locale where relevant in your app, you can easily make it strictly-typed later on if you like to do so.

@dBianchii
Copy link
Contributor

Really great! Feels good being able to just import the type of Locales directly from next-intl. Also, feels better to define the types with declare module 'next-intl' { } instead of declaring a global like before.

Excited for v4 and for Next.JS 15 support 🎉

@amannn
Copy link
Owner Author

amannn commented Nov 3, 2024

@dBianchii Awesome, thanks a lot for having a look! 🙌

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants