Add strict navigation return types to all screens
This would move us away from returning JSX.Element for the majority of our functional screens.
The documentation on organizing types from react navigation shows that we can strongly type the return for our screens. Are we interested in refactoring every screen to be checked in this way?
Organizing types
When writing types for React Navigation, there are a couple of things we recommend to keep things organized.
- It's good to create a separate files (e.g. navigation/types.tsx) which contains the types related to React Navigation.
- Instead of using CompositeNavigationProp directly in your components, it's better to create a helper type that you can reuse.
- Specifying a global type for your root navigator would avoid manual annotations in many places.
Considering these recommendations, the file containing the types may look something like this:
import type {
CompositeScreenProps,
NavigatorScreenParams,
} from '@react-navigation/native';
import type { StackScreenProps } from '@react-navigation/stack';
import type { BottomTabScreenProps } from '@react-navigation/bottom-tabs';
export type RootStackParamList = {
Home: NavigatorScreenParams<HomeTabParamList>;
PostDetails: { id: string };
NotFound: undefined;
};
export type RootStackScreenProps<T extends keyof RootStackParamList> =
StackScreenProps<RootStackParamList, T>;
export type HomeTabParamList = {
Popular: undefined;
Latest: undefined;
};
export type HomeTabScreenProps<T extends keyof HomeTabParamList> =
CompositeScreenProps<
BottomTabScreenProps<HomeTabParamList, T>,
RootStackScreenProps<keyof RootStackParamList>
>;
declare global {
namespace ReactNavigation {
interface RootParamList extends RootStackParamList {}
}
}
Now, when annotating your components, you can write:
import type { HomeTabScreenProps } from './navigation/types';
function PopularScreen({ navigation, route }: HomeTabScreenProps<'Popular'>) {
// ...
}
If you're using hooks such as useRoute, you can write:
import type { HomeTabScreenProps } from './navigation/types';
function PopularScreen() {
const route = useRoute<HomeTabScreenProps<'Popular'>['route']>();
// ...
}
We can also annotate useNavigation and useRoute with these patterns.
They do provide one warning about type safety, though.
It's important to note that this isn't completely type-safe because the type parameter you use may not be correct and we cannot statically verify it.