Skip to main content
Version: 7.x

使用 TypeScript 进行类型检查

React Navigation 可以配置为使用 TypeScript 对屏幕及其参数以及各种其他 API 进行类型检查。这在使用 React Navigation 时提供了更好的智能感知和类型安全性。

¥React Navigation can be configured to type-check screens and their params, as well as various other APIs using TypeScript. This provides better intelliSense and type safety when working with React Navigation.

使用静态 API 配置 TypeScript 有 2 个步骤:

¥There are 2 steps to configure TypeScript with the static API:

  1. 每个屏幕组件都需要指定它接受的 route.params 属性的类型。StaticScreenProps 类型使其更简单:

    ¥Each screen component needs to specify the type of the route.params prop that it accepts. The StaticScreenProps type makes it simpler:

    import type { StaticScreenProps } from '@react-navigation/native';

    type Props = StaticScreenProps<{
    username: string;
    }>;

    function ProfileScreen({ route }: Props) {
    // ...
    }
  2. 为根导航器生成 ParamList 类型并将其指定为 RootParamList 类型的默认类型:

    ¥Generate the ParamList type for the root navigator and specify it as the default type for the RootParamList type:

    import type { StaticParamList } from '@react-navigation/native';

    const HomeTabs = createBottomTabNavigator({
    screens: {
    Feed: FeedScreen,
    Profile: ProfileScreen,
    },
    });

    const RootStack = createNativeStackNavigator({
    screens: {
    Home: HomeTabs,
    },
    });

    type RootStackParamList = StaticParamList<typeof RootStack>;

    declare global {
    namespace ReactNavigation {
    interface RootParamList extends RootStackParamList {}
    }
    }

    这需要对 useNavigation 钩子进行类型检查。

    ¥This is needed to type-check the useNavigation hook.

¥Navigator specific types

通常,我们建议使用 useNavigation prop 的默认类型以与导航器无关的方式访问导航对象。但是,如果你需要使用特定于导航器的 API,则需要手动注释 useNavigation

¥Generally, we recommend using the default types for the useNavigation prop to access the navigation object in a navigator-agnostic manner. However, if you need to use navigator-specific APIs, you need to manually annotate useNavigation:

type BottomTabParamList = StaticParamList<typeof BottomTabNavigator>;
type ProfileScreenNavigationProp = BottomTabNavigationProp<
BottomTabParamList,
'Profile'
>;

// ...

const navigation = useNavigation<ProfileScreenNavigationProp>();

请注意,以这种方式注释 useNavigation 不是类型安全的,因为我们无法保证你提供的类型与导航器的类型匹配。

¥Note that annotating useNavigation this way is not type-safe since we can't guarantee that the type you provided matches the type of the navigator.

使用动态 API 嵌套导航器

¥Nesting navigator using dynamic API

考虑以下示例:

¥Consider the following example:

const Tab = createBottomTabNavigator();

function HomeTabs() {
return (
<Tab.Navigator>
<Tab.Screen name="Feed" component={FeedScreen} />
<Tab.Screen name="Profile" component={ProfileScreen} />
</Tab.Navigator>
);
}

const RootStack = createStackNavigator({
Home: HomeTabs,
});

此处,HomeTabs 组件使用动态 API 定义。这意味着当我们使用 StaticParamList<typeof RootStack> 为根导航器创建参数列表时,它不会知道嵌套导航器中定义的屏幕。为了解决这个问题,我们需要明确指定嵌套导航器的参数列表。

¥Here, the HomeTabs component is defined using the dynamic API. This means that when we create the param list for the root navigator with StaticParamList<typeof RootStack>, it won't know about the screens defined in the nested navigator. To fix this, we'd need to specify the param list for the nested navigator explicitly.

这可以通过使用屏幕组件接收的 route prop 的类型来完成:

¥This can be done by using the type of the route prop that the screen component receives:

type HomeTabsParamList = {
Feed: undefined;
Profile: undefined;
};

type HomeTabsProps = StaticScreenProps<
NavigatorScreenParams<HomeTabsParamList>
>;

function HomeTabs(_: HomeTabsProps) {
return (
<Tab.Navigator>
<Tab.Screen name="Feed" component={FeedScreen} />
<Tab.Screen name="Profile" component={ProfileScreen} />
</Tab.Navigator>
);
}

现在,使用 StaticParamList<typeof RootStack> 时,它将包括嵌套导航器中定义的屏幕。

¥Now, when using StaticParamList<typeof RootStack>, it will include the screens defined in the nested navigator.