Skip to content

Commit 67507cc

Browse files
authored
fix: Accept a deep partial of Messages for messages prop of provider (#1679)
([ref](#1631 (comment)))
1 parent 5b218d4 commit 67507cc

File tree

5 files changed

+54
-55
lines changed

5 files changed

+54
-55
lines changed

examples/example-app-router-playground/src/components/TypePortabilityTest.ts

+6-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import {
77
createFormatter,
8-
initializeConfig,
8+
createTranslator,
99
useFormatter,
1010
useLocale,
1111
useMessages,
@@ -60,9 +60,12 @@ export async function asyncApis() {
6060
}
6161

6262
export const withNextIntl = createNextIntlPlugin();
63-
export const config = initializeConfig({locale: 'en'});
64-
// export const translator = createTranslator({locale: 'en'});
63+
6564
export const formatter = createFormatter({
6665
locale: 'en',
6766
now: new Date(2022, 10, 6, 20, 20, 0, 0)
6867
});
68+
69+
export const translator = createTranslator({
70+
locale: 'en'
71+
});
+40-42
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,56 @@
1-
import type AbstractIntlMessages from './AbstractIntlMessages.js';
2-
import type {Locale} from './AppConfig.js';
1+
import type {Locale, Messages} from './AppConfig.js';
32
import type Formats from './Formats.js';
43
import type IntlError from './IntlError.js';
54
import type TimeZone from './TimeZone.js';
5+
import type {DeepPartial} from './types.js';
66

77
/**
88
* Should be used for entry points that configure the library.
99
*/
1010

11-
type IntlConfig<Messages extends AbstractIntlMessages = AbstractIntlMessages> =
12-
{
13-
/** A valid Unicode locale tag (e.g. "en" or "en-GB"). */
14-
locale: Locale;
15-
/** Global formats can be provided to achieve consistent
16-
* formatting across components. */
17-
formats?: Formats;
18-
/** A time zone as defined in [the tz database](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) which will be applied when formatting dates and times. If this is absent, the user time zone will be used. You can override this by supplying an explicit time zone to `formatDateTime`. */
19-
timeZone?: TimeZone;
20-
/** This callback will be invoked when an error is encountered during
21-
* resolving a message or formatting it. This defaults to `console.error` to
22-
* keep your app running. You can customize the handling by taking
23-
* `error.code` into account. */
24-
onError?(error: IntlError): void;
25-
/** Will be called when a message couldn't be resolved or formatting it led to
26-
* an error. This defaults to `${namespace}.${key}` You can use this to
27-
* customize what will be rendered in this case. */
28-
getMessageFallback?(info: {
29-
error: IntlError;
30-
key: string;
31-
namespace?: string;
32-
}): string;
33-
/**
34-
* Providing this value will have two effects:
35-
* 1. It will be used as the default for the `now` argument of
36-
* `useFormatter().formatRelativeTime` if no explicit value is provided.
37-
* 2. It will be returned as a static value from the `useNow` hook. Note
38-
* however that when `updateInterval` is configured on the `useNow` hook,
39-
* the global `now` value will only be used for the initial render, but
40-
* afterwards the current date will be returned continuously.
41-
*/
42-
now?: Date;
43-
/** All messages that will be available. */
44-
messages?: Messages;
45-
};
11+
type IntlConfig = {
12+
/** A valid Unicode locale tag (e.g. "en" or "en-GB"). */
13+
locale: Locale;
14+
/** Global formats can be provided to achieve consistent
15+
* formatting across components. */
16+
formats?: Formats;
17+
/** A time zone as defined in [the tz database](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) which will be applied when formatting dates and times. If this is absent, the user time zone will be used. You can override this by supplying an explicit time zone to `formatDateTime`. */
18+
timeZone?: TimeZone;
19+
/** This callback will be invoked when an error is encountered during
20+
* resolving a message or formatting it. This defaults to `console.error` to
21+
* keep your app running. You can customize the handling by taking
22+
* `error.code` into account. */
23+
onError?(error: IntlError): void;
24+
/** Will be called when a message couldn't be resolved or formatting it led to
25+
* an error. This defaults to `${namespace}.${key}` You can use this to
26+
* customize what will be rendered in this case. */
27+
getMessageFallback?(info: {
28+
error: IntlError;
29+
key: string;
30+
namespace?: string;
31+
}): string;
32+
/**
33+
* Providing this value will have two effects:
34+
* 1. It will be used as the default for the `now` argument of
35+
* `useFormatter().formatRelativeTime` if no explicit value is provided.
36+
* 2. It will be returned as a static value from the `useNow` hook. Note
37+
* however that when `updateInterval` is configured on the `useNow` hook,
38+
* the global `now` value will only be used for the initial render, but
39+
* afterwards the current date will be returned continuously.
40+
*/
41+
now?: Date;
42+
/** All messages that will be available. */
43+
messages?: DeepPartial<Messages>;
44+
};
4645

46+
/**
4747
/**
4848
* A stricter set of the configuration that should be used internally
4949
* once defaults are assigned to `IntlConfiguration`.
5050
*/
51-
export type InitializedIntlConfig<
52-
Messages extends AbstractIntlMessages = AbstractIntlMessages
53-
> = IntlConfig<Messages> & {
54-
onError: NonNullable<IntlConfig<Messages>['onError']>;
55-
getMessageFallback: NonNullable<IntlConfig<Messages>['getMessageFallback']>;
51+
export type InitializedIntlConfig = IntlConfig & {
52+
onError: NonNullable<IntlConfig['onError']>;
53+
getMessageFallback: NonNullable<IntlConfig['getMessageFallback']>;
5654
};
5755

5856
export default IntlConfig;

packages/use-intl/src/core/createTranslator.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ export default function createTranslator<
118118
namespace,
119119
onError = defaultOnError,
120120
...rest
121-
}: Omit<IntlConfig<TranslatorMessages>, 'messages'> & {
121+
}: Omit<IntlConfig, 'messages'> & {
122122
messages?: TranslatorMessages;
123123
namespace?: Namespace;
124124
/** @private */

packages/use-intl/src/core/types.tsx

+6
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,9 @@
22
export type Prettify<T> = {
33
[K in keyof T]: T[K];
44
} & {};
5+
6+
export type DeepPartial<Type> = {
7+
[Key in keyof Type]?: Type[Key] extends object
8+
? DeepPartial<Type[Key]>
9+
: Type[Key];
10+
};

packages/use-intl/src/react/useTranslations.test.tsx

+1-9
Original file line numberDiff line numberDiff line change
@@ -745,13 +745,7 @@ describe('error handling', () => {
745745
const onError = vi.fn();
746746

747747
render(
748-
<IntlProvider
749-
locale="en"
750-
// @ts-expect-error The types don't allow this,
751-
// but this shouldn't lead to an error.
752-
messages={{a: null}}
753-
onError={onError}
754-
>
748+
<IntlProvider locale="en" messages={{a: null}} onError={onError}>
755749
<span />
756750
</IntlProvider>
757751
);
@@ -878,7 +872,6 @@ describe('error handling', () => {
878872
render(
879873
<IntlProvider
880874
locale="en"
881-
// @ts-expect-error Arrays are not allowed
882875
messages={{Component: {array: ['a', 'b']}}}
883876
onError={onError}
884877
>
@@ -904,7 +897,6 @@ describe('error handling', () => {
904897
render(
905898
<IntlProvider
906899
locale="en"
907-
// @ts-expect-error Arrays are not allowed
908900
messages={{Component: {array: ['a', 'b']}}}
909901
onError={onError}
910902
>

0 commit comments

Comments
 (0)