TypeScript integration
next-intl
integrates seamlessly with TypeScript right out of the box, requiring no additional setup.
However, you can optionally provide supplemental type definitions for your messages and formats to enable autocompletion and improve type safety.
Messages
Messages can be strictly typed to ensure you’re using valid keys.
{
"About": {
"title": "Hello"
}
}
function About() {
// ✅ Valid namespace
const t = useTranslations('About');
// ✖️ Unknown message key
t('description');
// ✅ Valid message key
t('title');
}
To enable this validation, add a global type definition file in your project root (e.g. global.d.ts
):
import en from './messages/en.json';
type Messages = typeof en;
declare global {
// Use type safe message keys with `next-intl`
interface IntlMessages extends Messages {}
}
You can freely define the interface, but if you have your messages available locally, it can be helpful to automatically create the interface based on the messages from your default locale by importing it.
Formats
Global formats that are referenced in calls like format.dateTime
can be strictly typed to ensure you’re using valid format names across your app.
function Component() {
const format = useFormatter();
// ✅ Valid format
format.number(2, 'precise');
// ✅ Valid format
format.list(['HTML', 'CSS', 'JavaScript'], 'enumeration');
// ✖️ Unknown format string
format.dateTime(new Date(), 'unknown');
// ✅ Valid format
format.dateTime(new Date(), 'short');
}
To enable this validation, export the formats that you’re using in your request configuration:
import {Formats} from 'next-intl';
export const formats = {
dateTime: {
short: {
day: 'numeric',
month: 'short',
year: 'numeric'
}
},
number: {
precise: {
maximumFractionDigits: 5
}
},
list: {
enumeration: {
style: 'long',
type: 'conjunction'
}
}
} satisfies Formats;
// ...
Now, a global type definition file in the root of your project can pick up the shape of your formats and use them for declaring the IntlFormats
interface:
import {formats} from './src/i18n/request';
type Formats = typeof formats;
declare global {
// Use type safe formats with `next-intl`
interface IntlFormats extends Formats {}
}
Troubleshooting
If you’re encountering problems, double check that:
- Your interface uses the correct name.
- You’re using TypeScript version 5 or later.
- You’re using correct paths for all modules you’re importing into your global declaration file.
- Your type declaration file is included in
tsconfig.json
. - Your editor has loaded the most recent type declarations. When in doubt, you can restart.