我正在尝试遵循 本指南使用 TypeScript 和 React Navigation 进行类型检查,但每当我尝试导航到另一个选项卡中的屏幕时,我都会收到此错误:
Argument of type '[AppRoutes.LIBRARY_TAB, { screen: AppRoutes; params: { title: string; }; }]' is not assignable to parameter of type '[screen: AppRoutes.LIBRARY_TAB] | [screen: AppRoutes.LIBRARY_TAB, params: LibraryStackParamList]'.
Type '[AppRoutes.LIBRARY_TAB, { screen: AppRoutes; params: { title: string; }; }]' is not assignable to type '[screen: AppRoutes.LIBRARY_TAB, params: LibraryStackParamList]'.
Type at position 1 in source is not compatible with type at position 1 in target.
Object literal may only specify known properties, and 'screen' does not exist in type 'LibraryStackParamList'.ts(2345)
这是我的组件道具:
type ConversationScreenProps = CompositeScreenProps<
StackScreenProps<HomeStackParamList, AppRoutes.CONVERSATION>,
BottomTabScreenProps<MainTabsParamList, AppRoutes.HOME_TAB>
>;
我正在像这样导航到屏幕:
navigation.navigate(AppRoutes.LIBRARY_TAB, {
screen: AppRoutes.MEDITATION_PLAYER, // This is where the error shows up
params: {
title: suggestedMeditation,
},
});
我的堆栈/选项卡嵌套结构是这样的:
- MainStack (NativeStackNavigator)
- MainTabs (BottomTabNavigator)
- HomeStack (StackNavigator, if I change this one to a NativeStackNavigator then I get an error about some gesture handler)
- ConversationScreen
- ...
- LibraryStack (StackNavigator)
- LibraryHomeScreen
- MeditationsScreen
- MeditationPlayerScreen
- ...
- PaywallStack (NativeStackNavigator)
- AuthScreen
- PlansScreen
- ...
以下是我的选项卡和堆栈的一些类型:
export type MainStackParamList = {
[AppRoutes.MAIN_TABS]: undefined;
[AppRoutes.AUTH]: {
justLogIn?: boolean;
};
[AppRoutes.PAYWALL_STACK]: undefined;
};
export type MainTabsParamList = {
[AppRoutes.HOME_TAB]: HomeStackParamList;
[AppRoutes.LIBRARY_TAB]: LibraryStackParamList;
...
};
export type LibraryStackParamList = {
[AppRoutes.LIBRARY_HOME]: undefined;
[AppRoutes.MEDITATIONS]: undefined;
[AppRoutes.MEDITATION_PLAYER]: {
title: string;
};
...
};
export type ConversationScreenParamList = {
conversationId?: string;
journalEntryText?: string;
myMapSection?: string;
myMapSectionResponse?: string;
newConvoTopic?: string;
};
export type HomeStackParamList = {
[AppRoutes.HOME_SCREEN]: undefined;
[AppRoutes.CONVERSATION]: ConversationScreenParamList | undefined;
...
};
这是我的选项卡/堆栈的更详细视图,以防有帮助:
const PaywallStackNav = createNativeStackNavigator<PaywallStackParamList>();
const PaywallStack = () => (
<PaywallStackNav.Navigator screenOptions={{ headerShown: false }}>
<PaywallStackNav.Screen name={AppRoutes.AUTH} component={Auth} />
<PaywallStackNav.Screen name={AppRoutes.PLANS} component={PlansScreen} />
</PaywallStackNav.Navigator>
);
const MainStack = createNativeStackNavigator<MainStackParamList>();
const Main = () => (
<MainStack.Navigator screenOptions={{ headerShown: false }}>
<MainStack.Screen name={AppRoutes.MAIN_TABS} component={MainTabs} />
<MainStack.Screen
name={AppRoutes.PAYWALL_STACK}
component={PaywallStack}
options={{ presentation: "modal" }}
/>
</MainStack.Navigator>
);
const Tabs = createBottomTabNavigator<MainTabsParamList>();
const LibraryStack = createStackNavigator<LibraryStackParamList>();
const HomeStack = createStackNavigator<HomeStackParamList>();
const LibraryTab = () => (
<LibraryStack.Navigator initialRouteName={AppRoutes.LIBRARY_HOME}>
<LibraryStack.Screen
name={AppRoutes.LIBRARY_HOME}
component={LibraryHomeScreen}
options={{ title: "Library" }}
/>
<LibraryStack.Screen
name={AppRoutes.MEDITATION_PLAYER}
component={MeditationPlayerScreen}
/>
</LibraryStack.Navigator>
);
const HomeTab = () => (
<HomeStack.Navigator initialRouteName={AppRoutes.HOME_SCREEN}>
<HomeStack.Screen name={AppRoutes.HOME_SCREEN} component={Home} />
<HomeStack.Screen name={AppRoutes.CONVERSATION} component={Conversation} />
</HomeStack.Navigator>
);
const MainTabs = () => (
<Tabs.Navigator initialRouteName={AppRoutes.HOME_TAB}>
<Tabs.Screen
name={AppRoutes.LIBRARY_TAB}
component={LibraryTab}
options={{
tabBarLabel: "Library",
tabBarIcon: ({ focused }) => <TabBarIcon focused={focused} icon="library-outline" />
}}
/>
<Tabs.Screen
name={AppRoutes.HOME_TAB}
component={HomeTab}
options={{
tabBarLabel: AppRoutes.HOME_SCREEN,
tabBarIcon: ({ focused }) => <TabBarIcon focused={focused} icon="home-outline" />
}}
/>
</Tabs.Navigator>
);
我很确定我需要使用复合导航器(因为我正在跨选项卡/堆栈导航),但似乎我做错了?知道我需要更改什么才能不会引发类型错误吗?
让我知道我是否应该包含任何其他特定信息或代码(例如我在哪里声明我的堆栈/选项卡)。
来自有关嵌套导航器类型检查的文档:
为了能够进行类型检查,我们需要从包含嵌套导航器的屏幕中提取参数。这可以使用 NavigatorScreenParams 实用程序来完成
所以你需要改变这个:
export type MainTabsParamList = {
[AppRoutes.HOME_TAB]: HomeStackParamList;
[AppRoutes.LIBRARY_TAB]: LibraryStackParamList;
...
};
对此:
export type MainTabsParamList = {
[AppRoutes.HOME_TAB]: NavigatorScreenParams<HomeStackParamList>;
[AppRoutes.LIBRARY_TAB]: <LibraryStackParamList>;
...
};