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.

注意

React Navigation 旨在与 TypeScript 中的 strict 模式配合使用。如果你不使用 strict 模式,某些事情可能无法按预期工作。

¥React Navigation is designed to work with strict mode in TypeScript. If you are not using strict mode, some things might not work as expected.

使用静态 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.