Georgi Traykov
Georgi Traykov

Reputation: 1

Argument of type '[never, { email: string; password: string; }]' is not assignable to parameter of type 'never'

I am working with expo and React Native, trying to push props to other screens using navigation. The code compiles and pushes the props, but I get this error when passing the props as a second argument to the navigation.navigate() function:

Argument of type '[never, { email: string; password: string; }]' is not assignable to parameter of type 'never'.

I also get this error when trying to navigate to a screen without passing props:

Argument of type 'string' is not assignable to parameter of type '{ key: string; params?: undefined; merge?: boolean | undefined; } | { name: "SignUp"; key?: string | undefined; params: undefined; merge?: boolean | undefined; } | { key: string; params?: { email: string; password: string; } | undefined; merge?: boolean | undefined; } | ... 10 more ... | { ...; }'.ts(2345)

It goes away when I add 'as never'.

This is where I call the function in my SignUp.tsx screen:

import { RootStackParamList } from "../../App";
import { NativeStackScreenProps } from "@react-navigation/native-stack";
type propsType = NativeStackScreenProps<RootStackParamList, 'SignUp'>;

const SignUp = (props: propsType) => {
    const {navigation} = props;

.......

            return(
               ...
                <MainButton 
                canGoBack 
                style={tw`h-20 justify-center mt-3 mx-auto`} 
                text={"Sign up"} 
                targetPage="Characteristics" 
                onPress={() => navigation.navigate("Characteristics" )} 
                navigationData={{ email: formInput.email, password: formInput.password }} />)

This is the App.tsx where I have the RootStackParamList type and also the Stack Navigator:

export type RootStackParamList = {
    Login: undefined;
    SignUp: undefined;
    ProfileSetup: undefined;
    ProfileSetupDetails: undefined;
    IdealMatch: undefined;
    Characteristics: {
        email: string,
        password: string;
    };
    Profile: undefined;
};

const Stack = createNativeStackNavigator<RootStackParamList>();

export type Props = NativeStackScreenProps<RootStackParamList, 'Characteristics'>;



const App: React.FC<RootStackParamList> = () => {
    return (
      <NavigationContainer>
          <Stack.Navigator>
              <Stack.Screen name="Login" component={Login}
                             options={{ headerShown: false }}/>
              <Stack.Screen name="SignUp" component={SignUp}
                             options={{ headerShown: false }}/>
              <Stack.Screen name="ProfileSetup" component={ProfileSetup}
                             options={{ headerShown: false }}/>
              <Stack.Screen name="ProfileSetupDetails" component={ProfileSetupDetails}
                             options={{ headerShown: false }}/>
              <Stack.Screen name="IdealMatch" component={IdealMatch}
                             options={{ headerShown: false }}/>
              <Stack.Screen name="Characteristics" component={Characteristics}
                             options={{ headerShown: false }}
                             />
              <Stack.Screen name="Profile" component={Profile}
                             options={{ headerShown: false }}/>
          </Stack.Navigator>
      </NavigationContainer>
    );
}

I need suggestions. I am relatively new to React Native and react navigation.

Creating a route const with the path name and the data I'm pushing and passing it to the navigate seemed to fix it, but I don't know if its ok to leave it like this:

const route = ["Characteristics", { email: formInput.email, password: formInput: password}];
navigation.navigate(...(route as never));

Upvotes: 0

Views: 299

Answers (2)

Chris Heald
Chris Heald

Reputation: 62648

I don't know the react-navigation package in particular, but regarding your as never cast, the issue is that your route is an array of the union type (string | params)[], rather than the tuple type [string, params]. When you spread an array into navigate, it won't accept anything but a string in the first parameter, but spreading your current route tells it that it might receive either a string or typeof params.

Rather than this:

const route = ["Characteristics", { email: "", password: ""}];

Add as const to your definition, which tells Typescript "this is a tuple type":

const routeTuple = ["Characteristics", { email: "", password: ""}] as const;

See this playground link for a demonstration of the difference.

The as never cast tells Typescript to ignore any inferred type data, and to just treat the given variable as never. It punches a hole in the typechecking, and should be done only very rarely, and when you specifically know that type overrides are appropriate.

Upvotes: 0

Georgi Traykov
Georgi Traykov

Reputation: 1

Fixed it by creating a navigation constant and removing the props: propsType arg from my SignUp screen:

const navigation = useNavigation<StackNavigationProp<RootStackParamList>>();

I still wonder if i have to create a new navigation constant on each screen of the stack?

Upvotes: 0

Related Questions