diff --git a/example/src/Screens/BottomTabs.tsx b/example/src/Screens/BottomTabs.tsx index 332da320..5ae63d51 100644 --- a/example/src/Screens/BottomTabs.tsx +++ b/example/src/Screens/BottomTabs.tsx @@ -5,6 +5,7 @@ import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityI import { getFocusedRouteNameFromRoute, ParamListBase, + NavigatorScreenParams, } from '@react-navigation/native'; import type { StackScreenProps } from '@react-navigation/stack'; import { @@ -15,7 +16,7 @@ import TouchableBounce from '../Shared/TouchableBounce'; import Albums from '../Shared/Albums'; import Contacts from '../Shared/Contacts'; import Chat from '../Shared/Chat'; -import SimpleStackScreen from './SimpleStack'; +import SimpleStackScreen, { SimpleStackParams } from './SimpleStack'; const getTabBarIcon = (name: string) => ({ color, @@ -26,7 +27,7 @@ const getTabBarIcon = (name: string) => ({ }) => ; type BottomTabParams = { - Article: undefined; + Article: NavigatorScreenParams; Albums: undefined; Contacts: undefined; Chat: undefined; diff --git a/example/src/Screens/MaterialBottomTabs.tsx b/example/src/Screens/MaterialBottomTabs.tsx index d03ae8ff..a8d796d9 100644 --- a/example/src/Screens/MaterialBottomTabs.tsx +++ b/example/src/Screens/MaterialBottomTabs.tsx @@ -1,13 +1,14 @@ import * as React from 'react'; import { StyleSheet } from 'react-native'; +import type { NavigatorScreenParams } from '@react-navigation/native'; import { createMaterialBottomTabNavigator } from '@react-navigation/material-bottom-tabs'; import Albums from '../Shared/Albums'; import Contacts from '../Shared/Contacts'; import Chat from '../Shared/Chat'; -import SimpleStackScreen from './SimpleStack'; +import SimpleStackScreen, { SimpleStackParams } from './SimpleStack'; type MaterialBottomTabParams = { - Article: undefined; + Article: NavigatorScreenParams; Albums: undefined; Contacts: undefined; Chat: undefined; diff --git a/example/src/Screens/SimpleStack.tsx b/example/src/Screens/SimpleStack.tsx index 744515e8..b5db352e 100644 --- a/example/src/Screens/SimpleStack.tsx +++ b/example/src/Screens/SimpleStack.tsx @@ -10,7 +10,7 @@ import Article from '../Shared/Article'; import Albums from '../Shared/Albums'; import NewsFeed from '../Shared/NewsFeed'; -type SimpleStackParams = { +export type SimpleStackParams = { Article: { author: string } | undefined; NewsFeed: { date: number }; Albums: undefined; diff --git a/packages/core/src/getActionFromState.tsx b/packages/core/src/getActionFromState.tsx index a142a08f..f3253734 100644 --- a/packages/core/src/getActionFromState.tsx +++ b/packages/core/src/getActionFromState.tsx @@ -1,11 +1,12 @@ import type { Route, PartialRoute, + ParamListBase, NavigationState, PartialState, CommonActions, } from '@react-navigation/routers'; -import type { PathConfig, PathConfigMap, NestedNavigateParams } from './types'; +import type { PathConfig, PathConfigMap, NavigatorScreenParams } from './types'; type ConfigItem = { initialRouteName?: string; @@ -18,7 +19,7 @@ type NavigateAction = { type: 'NAVIGATE'; payload: { name: string; - params?: NestedNavigateParams; + params?: NavigatorScreenParams; }; }; @@ -55,7 +56,10 @@ export default function getActionFromState( let current: PartialState | undefined = route?.state; let config: ConfigItem | undefined = normalizedConfig?.screens?.[route?.name]; - let params: NestedNavigateParams = { ...route.params }; + let params = { ...route.params } as NavigatorScreenParams< + ParamListBase, + NavigationState + >; let payload = route ? { name: route.name, params } : undefined; @@ -98,7 +102,10 @@ export default function getActionFromState( if (route.state) { params.params = { ...route.params }; - params = params.params; + params = params.params as NavigatorScreenParams< + ParamListBase, + NavigationState + >; } else { params.params = route.params; } diff --git a/packages/core/src/types.tsx b/packages/core/src/types.tsx index b1be0680..8c42eaf1 100644 --- a/packages/core/src/types.tsx +++ b/packages/core/src/types.tsx @@ -504,19 +504,31 @@ export type TypedNavigator< ) => null; }; -export type NestedNavigateParams = - | { - screen?: string; - params?: object; - initial?: boolean; - state?: never; - } +export type NavigatorScreenParams< + ParamList, + State extends NavigationState = NavigationState +> = | { screen?: never; params?: never; initial?: never; - state?: PartialState | State; - }; + state: PartialState | State | undefined; + } + | { + [RouteName in keyof ParamList]: undefined extends ParamList[RouteName] + ? { + screen: RouteName; + params?: ParamList[RouteName]; + initial?: boolean; + state?: never; + } + : { + screen: RouteName; + params: ParamList[RouteName]; + initial?: boolean; + state?: never; + }; + }[keyof ParamList]; export type PathConfig = { path?: string; diff --git a/packages/core/src/useNavigationBuilder.tsx b/packages/core/src/useNavigationBuilder.tsx index 4996c7d5..a62ee54d 100644 --- a/packages/core/src/useNavigationBuilder.tsx +++ b/packages/core/src/useNavigationBuilder.tsx @@ -34,7 +34,7 @@ import { PrivateValueStore, EventMapBase, EventMapCore, - NestedNavigateParams, + NavigatorScreenParams, } from './types'; // This is to make TypeScript compiler happy @@ -43,7 +43,7 @@ PrivateValueStore; type NavigatorRoute = { key: string; - params?: NestedNavigateParams; + params?: NavigatorScreenParams; }; /**