Skip to content

Commit

Permalink
feat/typesafe-global-formats
Browse files Browse the repository at this point in the history
  • Loading branch information
dBianchii committed Sep 18, 2024
1 parent 2b36363 commit 7ab9a72
Show file tree
Hide file tree
Showing 6 changed files with 16,947 additions and 13,734 deletions.
3 changes: 3 additions & 0 deletions examples/example-app-router/global.d.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import en from './messages/en.json';
import {formats} from './src/i18n/request';

type Messages = typeof en;
type Formats = typeof formats;

declare global {
// Use type safe message keys with `next-intl`
interface IntlMessages extends Messages {}
interface IntlFormats extends Formats {}
}
28 changes: 26 additions & 2 deletions examples/example-app-router/src/i18n/request.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,29 @@
import {notFound} from 'next/navigation';
import {getRequestConfig} from 'next-intl/server';
import {routing} from './routing';
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'
}
}
} as const satisfies Partial<Formats>


export default getRequestConfig(async ({locale}) => {
// Validate that the incoming `locale` parameter is valid
Expand All @@ -12,6 +35,7 @@ export default getRequestConfig(async ({locale}) => {
? // When using Turbopack, this will enable HMR for `en`
import('../../messages/en.json')
: import(`../../messages/${locale}.json`))
).default
};
).default,
formats
}
});
8 changes: 4 additions & 4 deletions packages/use-intl/src/core/createFormatter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ export default function createFormatter({
value: Date | number,
/** If a time zone is supplied, the `value` is converted to that time zone.
* Otherwise the user time zone will be used. */
formatOrOptions?: string | DateTimeFormatOptions
formatOrOptions?: keyof IntlFormats['dateTime'] | DateTimeFormatOptions
) {
return getFormattedValue(
formatOrOptions,
Expand All @@ -183,7 +183,7 @@ export default function createFormatter({
end: Date | number,
/** If a time zone is supplied, the values are converted to that time zone.
* Otherwise the user time zone will be used. */
formatOrOptions?: string | DateTimeFormatOptions
formatOrOptions?: keyof IntlFormats['dateTime'] | DateTimeFormatOptions
) {
return getFormattedValue(
formatOrOptions,
Expand All @@ -200,7 +200,7 @@ export default function createFormatter({

function number(
value: number | bigint,
formatOrOptions?: string | NumberFormatOptions
formatOrOptions?: keyof IntlFormats['number'] | NumberFormatOptions
) {
return getFormattedValue(
formatOrOptions,
Expand Down Expand Up @@ -284,7 +284,7 @@ export default function createFormatter({
type FormattableListValue = string | ReactElement;
function list<Value extends FormattableListValue>(
value: Iterable<Value>,
formatOrOptions?: string | Intl.ListFormatOptions
formatOrOptions?: IntlFormats['list'] | Intl.ListFormatOptions
): Value extends string ? string : Iterable<ReactElement> {
const serializedValue: Array<string> = [];
const richValues = new Map<string, Value>();
Expand Down
6 changes: 6 additions & 0 deletions packages/use-intl/src/react/useFormatter.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ describe('dateTime', () => {
it('can use a global date format', () => {
function Component() {
const format = useFormatter();
// @ts-expect-error
return <>{format.dateTime(mockDate, 'onlyYear')}</>;
}

Expand All @@ -82,6 +83,7 @@ describe('dateTime', () => {
it('can use a global time format', () => {
function Component() {
const format = useFormatter();
// @ts-expect-error
return <>{format.dateTime(mockDate, 'onlyHours')}</>;
}

Expand Down Expand Up @@ -191,6 +193,7 @@ describe('dateTime', () => {

function Component() {
const format = useFormatter();
// @ts-expect-error
return <>{format.dateTime(mockDate, 'onlyYear')}</>;
}

Expand Down Expand Up @@ -218,6 +221,7 @@ describe('dateTime', () => {

function Component() {
const format = useFormatter();
// @ts-expect-error
return <>{format.dateTime(mockDate, 'medium')}</>;
}

Expand Down Expand Up @@ -315,6 +319,7 @@ describe('number', () => {
it('can use a global format', () => {
function Component() {
const format = useFormatter();
// @ts-expect-error
return <>{format.number(10000, 'noGrouping')}</>;
}

Expand Down Expand Up @@ -370,6 +375,7 @@ describe('number', () => {

function Component() {
const format = useFormatter();
// @ts-expect-error
return <>{format.number(mockNumber, 'missing')}</>;
}

Expand Down
10 changes: 9 additions & 1 deletion packages/use-intl/types/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
// This type is intended to be overridden
// by the consumer for optional type safety
// by the consumer for optional type safety of messages
declare interface IntlMessages extends Record<string, any> {}

// This type is intended to be overridden
// by the consumer for optional type safety of formats
declare interface IntlFormats {
dateTime: {};
number: {};
list: {};
}

// Temporarly copied here until the "es2020.intl" lib is published.

declare namespace Intl {
Expand Down
Loading

0 comments on commit 7ab9a72

Please sign in to comment.