Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

[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'.

like image 406
BattleVlog Avatar asked Aug 05 '21 13:08

BattleVlog


People also ask

How do I fix type string is not assignable to type never?

The error "Type is not assignable to type 'never'" occurs when we declare an empty array without explicitly typing it and attempt to mutate the array. To solve the error, explicitly type the empty array, e.g. const arr: string[] = []; .

What is never [] in react?

The type of the array is inferred to be never[] , in other words, an array that will always be empty, which is not what we want. To solve the error, use the generic on the useState hook to type the state array. App.tsx.

Is not assignable to parameter of type to?

The error "Argument of type string | undefined is not assignable to parameter of type string" occurs when a possibly undefined value is passed to a function that expects a string . To solve the error, use a type guard to verify the value is a string before passing it to the function.

What is never array?

This type represents an array that will never contain any elements (will always be empty). To solve the error, explicitly type the empty array.


4 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>
like image 172
Parterdev Avatar answered Oct 17 '22 06:10

Parterdev


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.

like image 30
Frédéric Fara Wat Avatar answered Oct 17 '22 05:10

Frédéric Fara Wat


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 {}
  }
}
like image 42
lee_mcmullen Avatar answered Oct 17 '22 06:10

lee_mcmullen


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;
like image 42
Daniel Alejandro Avatar answered Oct 17 '22 06:10

Daniel Alejandro