How do I Figure out React Navigation Return Types?

Viewed 573

I'm used to strongly typed languages, but still very new to TypeScript and I'm having difficulty with understanding the types of different methods and such from other libraries. But I'm using the react-navigation library and I'm trying to figure out the types of a few things related to the Stack screen navigation.

Here's some example code from the official page:

import { createStackNavigator } from '@react-navigation/stack';

const Stack = createStackNavigator();

function MyStack() {
  return (
    <Stack.Navigator>
      <Stack.Screen name="Home" component={Home} />
      <Stack.Screen name="Notifications" component={Notifications} />
      <Stack.Screen name="Profile" component={Profile} />
      <Stack.Screen name="Settings" component={Settings} />
    </Stack.Navigator>
  );
}

If I dig into the creatStackNavigator() implementation, I see:

declare function StackNavigator({ initialRouteName, children, screenOptions, ...rest }: Props): JSX.Element;

So does this function return a JSX.Element? If so, why is it that when I try to use this type...:

const Stack: JSX.Element = createStackNavigator();

... that I get this error?:

Type 'TypedNavigator<Record<string, object | undefined>, StackNavigationState, StackNavigationOptions, StackNavigationEventMap, ({ initialRouteName, children, screenOptions, ...rest }: Props) => Element>' is missing the following properties from type 'Element': type, props, keyts(2739)

I'm interested in the specifics of this case in React Navigation, as well as general tips to better figure out the return types of functions, components, etc.

Edit: Specifically in my use case, I'm hoping to do something like the following, where I can have a function take the StackNavigator and use it to create screens so that I can have uniform options for all of my screens:

import React from 'react';
import {View} from 'react-native';
import {NavigationContainer} from '@react-navigation/native';
import StackNavigator, TypedNavigator, {createStackNavigator} from '@react-navigation/stack';

const DummyView = () => {
    return <View/>;
}

// Instead of "any", what can I use as the type for stackNav?
// Neither StackNavigator or TypedNavigator seemed to work, at least not with the imports I have for them.
function createStackScreen (stackNav : any , name:string, component: React.ComponentType<any>) {
    // I also think I'll have problems with the Screen
    return (<stackNav.Screen
        name={name}
        component={component}
        options={{
        headerShown: false
    }}/>);
}

const MyStack = createStackNavigator();

const Index = () => {
    return (
        <NavigationContainer>
            <MyStack.Navigator>
                {createStackScreen(MyStack, 'Main Screen', DummyView)}
                {createStackScreen(MyStack, 'Secondary Screen', DummyView)}
                {createStackScreen(MyStack, 'Tertiary Screen', DummyView)}
            </MyStack.Navigator>
        </NavigationContainer>
    );
}

export default Index;
1 Answers

A react FunctionComponent is a function which takes a single argument which is a props object and returns a JSX.Element. The JSX.Element is the DOM representation of the component, which is usually an element like div, but it can also be a string, number, or null.

declare function StackNavigator({ initialRouteName, children, screenOptions, ...rest }: Props): JSX.Element;

This definition means that StackNavigator is a function component taking props which include the properties initialRouteName, etc.

Importantly, this is the definition of StackNavigator, not of createStackNavigator.

createStackNavigator is a function which returns a StackNavigator function component ( a higher-order function).

declare const _default: <ParamList extends Record<string, object | undefined>>()
 => TypedNavigator<ParamList, StackNavigationState, StackNavigationOptions, StackNavigationEventMap, typeof StackNavigator>;

So the type of Stack would be StackNavigator rather than JSX.Element (specifically it is a TypedNavigator with lots of generic parameters). It is a function which creates an element.

It is unnecessary to manually define any type for Stack since the type is already known to typescript based on the return type of createStackNavigator.

Related