Skip to content

Commit cf4a445

Browse files
committed
Use newer module augmentation for global types
1 parent bb50440 commit cf4a445

5 files changed

Lines changed: 43 additions & 34 deletions

File tree

versioned_docs/version-7.x/static-vs-dynamic.md

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -590,7 +590,7 @@ function ProfileScreen({ route }: ProfileScreenProps) {
590590
```
591591

592592
```ts title="Static API"
593-
import type { StaticScreenProps, StaticParamList } from '@react-navigation/native';
593+
import type { StaticScreenProps } from '@react-navigation/native';
594594

595595
type Props = StaticScreenProps<{ userId: string }>;
596596

@@ -604,16 +604,14 @@ const RootStack = createNativeStackNavigator({
604604
},
605605
});
606606

607-
type RootStackParamList = StaticParamList<typeof RootStack>;
607+
type RootStackType = typeof RootStack;
608608

609-
declare global {
610-
namespace ReactNavigation {
611-
interface RootParamList extends RootStackParamList {}
612-
}
609+
declare module '@react-navigation/core' {
610+
interface RootNavigator extends RootStackType {}
613611
}
614612
```
615613

616-
Here, the `StaticParamList` utility type generates the param list type from the navigator config. Declaring the global `RootParamList` interface enables type checking for [`useNavigation`](use-navigation.md), [`Link`](link.md) etc.
614+
Declaring the `RootNavigator` module augmentation lets React Navigation know about the navigator used at the root of your app. This enables type checking for [`useNavigation`](use-navigation.md), [`Link`](link.md) etc.
617615

618616
See [Configuring TypeScript](typescript.md) for more details.
619617

versioned_docs/version-7.x/typescript.md

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,9 @@ There are 2 steps to configure TypeScript with the static API:
3535
}
3636
```
3737

38-
2. Generate the `ParamList` type for the root navigator and specify it as the default type for the `RootParamList` type:
38+
2. Declare a module augmentation for `@react-navigation/core` and extend the `RootNavigator` interface with the type of your root navigator.
3939

4040
```ts
41-
import type { StaticParamList } from '@react-navigation/native';
42-
4341
const HomeTabs = createBottomTabNavigator({
4442
screens: {
4543
Feed: FeedScreen,
@@ -54,13 +52,11 @@ There are 2 steps to configure TypeScript with the static API:
5452
});
5553

5654
// highlight-next-line
57-
type RootStackParamList = StaticParamList<typeof RootStack>;
55+
type RootStackType = typeof RootStack;
5856

5957
// highlight-start
60-
declare global {
61-
namespace ReactNavigation {
62-
interface RootParamList extends RootStackParamList {}
63-
}
58+
declare module '@react-navigation/core' {
59+
interface RootNavigator extends RootStackType {}
6460
}
6561
// highlight-end
6662
```
@@ -369,7 +365,7 @@ type ProfileScreenNavigationProp = CompositeNavigationProp<
369365
:::danger
370366

371367
Annotating `useNavigation` isn't type-safe because the type parameter cannot be statically verified.
372-
Prefer [specifying a default type](#specifying-default-types-for-usenavigation-link-ref-etc) instead.
368+
Prefer [specifying the type of your root navigator](#specifying-default-types-for-usenavigation-link-ref-etc) instead.
373369

374370
:::
375371

@@ -473,19 +469,22 @@ const navigationRef =
473469

474470
## Specifying default types for `useNavigation`, `Link`, `ref` etc
475471

476-
Instead of manually annotating these APIs, you can specify a global type for your root navigator which will be used as the default type.
472+
Instead of manually annotating these APIs, you can specify the type of your root navigator, which will be used to infer the default types.
477473

478-
To do this, you can add this snippet somewhere in your codebase:
474+
To do this, you can use module augmentation for `@react-navigation/core` and extend the `RootNavigator` interface with the type of your root navigator:
479475

480-
```js
481-
declare global {
482-
namespace ReactNavigation {
483-
interface RootParamList extends RootStackParamList {}
484-
}
476+
```ts
477+
// highlight-next-line
478+
type RootStackType = typeof RootStack;
479+
480+
// highlight-start
481+
declare module '@react-navigation/core' {
482+
interface RootNavigator extends RootStackType {}
485483
}
484+
// highlight-end
486485
```
487486

488-
The `RootParamList` interface lets React Navigation know about the params accepted by your root navigator. Here we extend the type `RootStackParamList` because that's the type of params for our stack navigator at the root. The name of this type isn't important.
487+
This lets React Navigation know about the navigator used at the root of your app. Here we extend the `RootNavigator` interface with `RootStackType` because that's the type of the stack navigator at the root. The name of this type isn't important.
489488

490489
Specifying this type is important if you heavily use [`useNavigation`](use-navigation.md), [`Link`](link.md) etc. in your app since it'll ensure type-safety. It will also make sure that you have correct nesting on the [`linking`](navigation-container.md#linking) prop.
491490

@@ -495,7 +494,7 @@ When writing types for React Navigation, there are a couple of things we recomme
495494

496495
1. It's good to create a separate file (e.g. `navigation/types.tsx`) that contains the types related to React Navigation.
497496
2. Instead of using `CompositeNavigationProp` directly in your components, it's better to create a helper type that you can reuse.
498-
3. Specifying a global type for your root navigator would avoid manual annotations in many places.
497+
3. Specifying the type of your root navigator avoids manual annotations in many places.
499498

500499
Considering these recommendations, the file containing the types may look something like this:
501500

@@ -526,11 +525,24 @@ export type HomeTabScreenProps<T extends keyof HomeTabParamList> =
526525
BottomTabScreenProps<HomeTabParamList, T>,
527526
RootStackScreenProps<'Home'>
528527
>;
528+
```
529529

530-
declare global {
531-
namespace ReactNavigation {
532-
interface RootParamList extends RootStackParamList {}
533-
}
530+
Then, you'd set up the type for your root navigator in the same file where your root navigator is defined:
531+
532+
```ts
533+
import { createStackNavigator } from '@react-navigation/stack';
534+
import type { RootStackParamList } from './navigation/types';
535+
536+
const RootStack = createStackNavigator<RootStackParamList>();
537+
538+
function App() {
539+
// ...
540+
}
541+
542+
type RootStackType = typeof RootStack;
543+
544+
declare module '@react-navigation/core' {
545+
interface RootNavigator extends RootStackType {}
534546
}
535547
```
536548

versioned_docs/version-7.x/upgrading-from-6.x.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ or
209209
+ const props = useLinkProps({ screen: 'Details', params: { foo: 42 } });
210210
```
211211

212-
With this change, you'd now have full type-safety when using the `Link` component given that you have [configured the global type](typescript.md#specifying-default-types-for-usenavigation-link-ref-etc).
212+
With this change, you'd now have full type-safety when using the `Link` component given that you have [configured the type of your root navigator](typescript.md#specifying-default-types-for-usenavigation-link-ref-etc).
213213

214214
See [`Link`](link.md) and [`useLinkProps`](use-link-props.md) for usage.
215215

versioned_docs/version-8.x/typescript.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -792,7 +792,7 @@ When writing types for React Navigation, there are a couple of things we recomme
792792

793793
1. It's good to create a separate file (e.g. `navigation/types.tsx`) that contains the types related to React Navigation.
794794
2. Instead of using `CompositeNavigationProp` directly in your components, it's better to create a helper type that you can reuse.
795-
3. Specifying a global type for your root navigator would avoid manual annotations in many places.
795+
3. Specifying the type of your root navigator avoids manual annotations in many places.
796796

797797
Considering these recommendations, the file containing the types may look something like this:
798798

@@ -825,7 +825,7 @@ export type HomeTabScreenProps<T extends keyof HomeTabParamList> =
825825
>;
826826
```
827827

828-
Then, you'd set up the global type for your root navigator in the same file where your root navigator is defined:
828+
Then, you'd set up the type for your root navigator in the same file where your root navigator is defined:
829829

830830
```ts
831831
import { createStackNavigator } from '@react-navigation/stack';
@@ -837,7 +837,6 @@ function App() {
837837
// ...
838838
}
839839

840-
// Specify the global type for the root navigator
841840
type RootStackType = typeof RootStack;
842841

843842
declare module '@react-navigation/core' {

versioned_docs/version-8.x/upgrading-from-7.x.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ We introduced a static API in React Navigation 7. However, some of the TypeScrip
6161

6262
#### The root type now uses navigator type instead of param list
6363

64-
Previously the types for the root navigator were specified using `declare global` and `RootParamList`. Now, they can be specified with module augmentation of `@react-navigation/core` and use the navigator's type instead a param list:
64+
Previously the types for the root navigator were specified using `declare global` and `RootParamList`. Now, they can be specified with module augmentation of `@react-navigation/core` and use the navigator's type instead of a param list:
6565

6666
```diff lang=ts
6767
- type RootStackParamList = StaticParamList<typeof RootStack>;

0 commit comments

Comments
 (0)