Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add strict navigation return types to all screens #6044

Open
drewvolz opened this issue May 8, 2022 · 1 comment
Open

Add strict navigation return types to all screens #6044

drewvolz opened this issue May 8, 2022 · 1 comment

Comments

@drewvolz
Copy link
Member

drewvolz commented May 8, 2022

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.

  1. It's good to create a separate files (e.g. navigation/types.tsx) which contains the types related to React Navigation.
  2. Instead of using CompositeNavigationProp directly in your components, it's better to create a helper type that you can reuse.
  3. 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']>();

  // ...
}
@drewvolz
Copy link
Member Author

drewvolz commented May 8, 2022

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant