Passing useState as props in typescript

Adding onto @fiz's comment, his code of block was slightly not working for me:

import React, { Dispatch, SetStateAction } from 'react';

const MyChildComponent1 = (
  myVar: boolean,
  setMyVar: Dispatch<SetStateAction<<boolean>>
) => {...};

I had to set setMyVar: Dispatch<SetStateAction<boolean>> (there was one too many brackets)


Dispatch & SetStateAction types

As @Retsam mentioned, you can also import and use the types Dispatch and SetStateAction from React:

import React, { Dispatch, SetStateAction } from 'react';

const MyChildComponent1 = (
  myVar: boolean,
  setMyVar: Dispatch<SetStateAction<boolean>>
) => {...};

Bonus

When I find myself frequently using this, I create a type alias to help with readability

import React, { Dispatch, SetStateAction } from 'react';

type Dispatcher<S> = Dispatch<SetStateAction<S>>;

const MyChildComponent1 = (
  myVar: boolean,
  setMyVar: Dispatcher<boolean>,
) => {...};

hope this helps.


It can also be done like this using Interface and React components.

MainComponent.tsx

Value assignment of the useState component defined in Main is done in the child component. When this field is triggered, the code in useEffect will run.

import React, { useEffect } from 'react';
import Login from './views/Login/index';

const App: React.FunctionComponent = () => {
    const [isAuthenticated, setAuthenticatedStatus] = React.useState(false);

    useEffect(() => {
        if (isAuthenticated)
            window.location.href = "<redirect url>";
    }, [isAuthenticated]);

    return (<Login setLoginStatus={setAuthenticatedStatus} />)
};

export default App;

ChildComponent.tsx

import { Dispatch, SetStateAction, FunctionComponent } from 'react';
import authService from '../../apiServices/authService';

interface IProps {
   setLoginStatus: Dispatch<SetStateAction<boolean>>;
}

const Login: FunctionComponent<IProps> = (props: IProps) => {

   const login = async (username: string, password: string) => {
      const response = await authService.authenticateUser(username, password);

      if (response && response.statusCode == 200 && response.result.accessToken) {
         props.setLoginStatus(true);
      }
      else {
         // ...
      }
   };


   return (
      <>
         ...
      </>
   );
};

export default Login;

The type that would match the function returned from invoking useState would be:

setMyVar: (value: boolean | ((prevVar: boolean) => boolean)) => void;

If we look at the type definition file from DefinitelyTyped [1], we can see that the second type in the return type is a dispatch:

function useState<S>(initialState: S | (() => S)): [S, Dispatch<SetStateAction<S>>];

Thus the generic type provided is passed through to SetStateAction<S>, which is defined as:

type SetStateAction<S> = S | ((prevState: S) => S);

So essentially, an interface for your component would be the following:

interface IProps {
  myVar: boolean;
  setMyVar?: (value: boolean | (prevVar: boolean) => boolean) => void;
}

As @Retsam said, it's best to use React's exported types:

import { Dispatch, SetStateAction } from "react";

interface IProps {
  myVar: boolean;
  setMyVar?: Dispatch<SetStateAction<boolean>>;
}

References: [1] https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/react/index.d.ts#L845