Skip to content

Commit

Permalink
fix: wrong setParams type if route does not have params (#10512)
Browse files Browse the repository at this point in the history
If a RouteList type has a route with params set to undefined, for example:

```ts
type ExampleRouteList = {
  HasArgs: {someArg?: string};
  NoArgs: undefined;
};
```

Then `navigation.setParams` for `NoArgs` would be typed as `(params: Partial<unknown>): void`, since
`NavigationProp` would type it as `(params: Partial<RouteList[RouteName]>): void`.

This would cause issues with `CompositeScreenProps` because a route with `undefined` params
would not extend the `NavigationProp` type correctly, so that screen would not actually get
all the options the parent navigators have available.

Conditionally setting `setParams` to `undefined` if `RouteList[RouteName]` extends `undefined`
fixes this issue.
  • Loading branch information
Gustash committed Aug 7, 2022
1 parent 50b88d4 commit 8ed42cd
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 15 deletions.
78 changes: 64 additions & 14 deletions example/types.check.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import type { BottomTabScreenProps } from '@react-navigation/bottom-tabs';
import type { DrawerScreenProps } from '@react-navigation/drawer';
import type {
BottomTabNavigationOptions,
BottomTabScreenProps,
} from '@react-navigation/bottom-tabs';
import type {
DrawerNavigationOptions,
DrawerScreenProps,
} from '@react-navigation/drawer';
import type {
CompositeScreenProps,
NavigatorScreenParams,
} from '@react-navigation/native';
import type { StackNavigationOptions } from '@react-navigation/stack';
import {
createStackNavigator,
StackScreenProps,
Expand Down Expand Up @@ -70,10 +77,9 @@ export const PostDetailsScreen = ({
.parameter(0)
.toEqualTypeOf<keyof RootStackParamList>();

expectTypeOf(navigation.setOptions).parameter(0).toMatchTypeOf<{
title?: string;
headerShown?: boolean;
}>();
expectTypeOf(navigation.setOptions)
.parameter(0)
.toMatchTypeOf<StackNavigationOptions>();

expectTypeOf(navigation.addListener)
.parameter(0)
Expand Down Expand Up @@ -113,10 +119,12 @@ export const FeedScreen = ({

expectTypeOf(navigation.openDrawer).toBeFunction();

expectTypeOf(navigation.setOptions).parameter(0).toMatchTypeOf<{
title?: string;
lazy?: boolean;
}>();
expectTypeOf(navigation.setOptions)
.parameter(0)
.toMatchTypeOf<StackNavigationOptions>();
expectTypeOf(navigation.setOptions)
.parameter(0)
.toMatchTypeOf<DrawerNavigationOptions>();

expectTypeOf(navigation.addListener)
.parameter(0)
Expand Down Expand Up @@ -145,17 +153,59 @@ export const PopularScreen = ({

expectTypeOf(navigation.openDrawer).toBeFunction();

expectTypeOf(navigation.setOptions).parameter(0).toMatchTypeOf<{
title?: string;
taBarLabel?: string;
}>();
expectTypeOf(navigation.setOptions)
.parameter(0)
.toMatchTypeOf<StackNavigationOptions>();
expectTypeOf(navigation.setOptions)
.parameter(0)
.toMatchTypeOf<DrawerNavigationOptions>();
expectTypeOf(navigation.setOptions)
.parameter(0)
.toMatchTypeOf<BottomTabNavigationOptions>();

expectTypeOf(navigation.addListener)
.parameter(0)
.toEqualTypeOf<
'focus' | 'blur' | 'state' | 'beforeRemove' | 'tabPress' | 'tabLongPress'
>();

expectTypeOf(navigation.setParams)
.parameter(0)
.toEqualTypeOf<Partial<FeedTabParamList['Popular']>>();

expectTypeOf(navigation.getState().type).toEqualTypeOf<'tab'>();
expectTypeOf(navigation.getParent)
.parameter(0)
.toEqualTypeOf<'LeftDrawer' | 'BottomTabs' | undefined>();
};

export const LatestScreen = ({
navigation,
route,
}: FeedTabScreenProps<'Latest'>) => {
expectTypeOf(route.name).toEqualTypeOf<'Latest'>();

expectTypeOf(navigation.push)
.parameter(0)
.toEqualTypeOf<keyof RootStackParamList>();
expectTypeOf(navigation.jumpTo)
.parameter(0)
.toEqualTypeOf<keyof HomeDrawerParamList>();

expectTypeOf(navigation.openDrawer).toBeFunction();

expectTypeOf(navigation.setOptions)
.parameter(0)
.toMatchTypeOf<StackNavigationOptions>();
expectTypeOf(navigation.setOptions)
.parameter(0)
.toMatchTypeOf<DrawerNavigationOptions>();
expectTypeOf(navigation.setOptions)
.parameter(0)
.toMatchTypeOf<BottomTabNavigationOptions>();

expectTypeOf(navigation.setParams).parameter(0).toEqualTypeOf<undefined>();

expectTypeOf(navigation.getState().type).toEqualTypeOf<'tab'>();
expectTypeOf(navigation.getParent)
.parameter(0)
Expand Down
6 changes: 5 additions & 1 deletion packages/core/src/types.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,11 @@ export type NavigationProp<
*
* @param params Params object for the current route.
*/
setParams(params: Partial<ParamList[RouteName]>): void;
setParams(
params: ParamList[RouteName] extends undefined
? undefined
: Partial<ParamList[RouteName]>
): void;

/**
* Update the options for the route.
Expand Down

0 comments on commit 8ed42cd

Please sign in to comment.