react native typescript 'string' is not assignable to parameter of type 'never.' in useNavigation

Viewed 12755

[I keep getting the error that says 'string' is not assignable to parameter of type 'never' in react native typescript and I don't know why. Can someone help me fix this bug.

Thank you in advance.]1

code snippet :

const loadReport = (id: string) => {
    setPostId(id);
    navigation.navigate('Report', {postId: id});
}

I get an underline under 'Report'.

6 Answers

This is a weird issue that happens in RN > 0.65. My solution:

1.- Import:

{/* Depends of your Package (Stack or NativeStack...) */}
import { StackNavigationProp } from '@react-navigation/stack';
import { useNavigation } from '@react-navigation/core';

2.- Define types

export type RootStackParamList = {
  YourScreen: { id: string };
};

3.- Assign useNavigation hook with type StackNavigationProp.

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

4.- Use it! (Eye: with this type you can access to navigation object)

<TouchableOpacity 
   onPress={() => navigation.navigate('YourScreen', {id: 'smth'})}>
</TouchableOpacity>

The only solution I found is to apply the type never on the string name.

const goToContent = () => {
    navigate("Content" as never, {} as never);
};

I'm not sure it's the best solution but it's work.

I too was getting the following ts error when not annotating useNavigation and trying to call navigation.navigate('OtherJazzyScreen)`:

Argument of type 'string' is not assignable to parameter of type '{ key: string; params?: undefined; merge?: boolean | undefined; } | { name: never; key?: string | undefined; params: never; merge?: boolean | undefined; }'

The OP doesn't specify which version of react-navigation they're using but you can fix this globally in React Navigation 6 which means you then don't have to annotate useNavigation directly but you still get autocomplete and type checking.

Taken from the react-navigation blog in August 2021 (https://reactnavigation.org/blog/2021/08/14/react-navigation-6.0/#better-type-safety):

In React Navigation 6, you don’t need to annotate useNavigation to get autocompletion and type checking. This is possible by defining a type for the screens globally using declaration merging:

declare global {   
  namespace ReactNavigation {
    interface RootParamList {
      Home: undefined;
      Profile: { userId: string };
      NotFound: undefined;
    }   
  } 
 } 

You can read more about it in our TypeScript docs.

Another example from the React Navigation 6 docs, if you already have your params declared elsewhere:

// E.g. RootStackParamList.ts
export type RootStackParamList = {
  Home: undefined;
  Profile: { userId: string };
  NotFound: undefined;
};

// E.g. App.tsx
import { RootStackParamList } from 'path/to/RootStackParamList';
declare global {
  namespace ReactNavigation {
    interface RootParamList extends RootStackParamList {}
  }
}

Simple solution is to add any to NativeStackNavigationProp type

const AppLink = ({
  text,
  screenName,
}: Link) => {

  // pass any to overload 
  const navigation = useNavigation<NativeStackNavigationProp<any>>();

  const handleNavigation = () => {
    navigation.navigate(screenName);
  };  
  
  return (
    <TouchableOpacity onPress={handleNavigation}>
      <Text>{text}</Text>
    </TouchableOpacity>
  );
};

export default AppLink;

You could make a maintainable navigation prop.

  1. Make a type file.
// navigation.ts
import { DrawerNavigationProp } from "@react-navigation/drawer";
import { NavigationProp } from "@react-navigation/native";
import { StackNavigationProp } from "@react-navigation/stack";

type RootStackParamList = {
  // Your custom param type belongs here.
  Login: {
    id: string;
  },
  Profile: {}, 
}

type RootDrawerParamList = {
  Shopping: {},
  Chat: {},
}

export type RootNavigationProp = NavigationProp<
 StackNavigationProp<RootStackParamList>,
 DrawerNavigationProp<RootDrawerParamList>
>;
  1. Use it.
import { useNavigation } from "@react-navigation/native";
import { RootNavigationProp } from "@somewhere/navigation";

const App = () => {
  const navigation = useNavigation<RootNavigationProp>();

  function onPress () {
    navigation.navigate("Login", {id: "userID"});
  }
}

Just use type any when calling the hook:

const navigation = useNavigation<any>();
Related