How to type the setState function from the useState hook

Saturday, February 22, 2025

Imagine you have a component with a number state, and you pass the same state into another component for it to be used:

import { useState } from 'react';
import { Snippets } from './snippets';
 
export const Sample = () => {
  const [number, setNumber] = useState<number>(0);
 
  return <Snippets number={number} setNumber={setNumber} />;
};

What should the SnippetsProps interface look like?

Most people will type something like this:

import { Dispatch, SetStateAction } from 'react';
 
interface SnippetsProps {
  number: number;
  setNumber: Dispatch<SetStateAction<number>>;
}
 
export const Snippets = ({ number, setNumber }: SnippetsProps) => {
  return (
    <div>
      <span>Clicked {number} times</span>
      <button onClick={() => setNumber(number + 1)}>Click me</button>
    </div>
  );
};

But it bothers me to have to import Dispatch and SetStateAction from react just to be able to define the interface.

The type Dispatch<SetStateAction<T>> here is basically a function that accepts whatever type you declared your state is, in this case, it's a number.

So basically you can also do this here:

interface SnippetsProps {
  number: number;
  setNumber: (v: number) => void;
}
 
export const Snippets = ({ number, setNumber }: SnippetsProps) => {
  return (
    <div>
      <span>Clicked {number} times</span>
      <button onClick={() => setNumber(number + 1)}>Click me</button>
    </div>
  );
};

We just saved two imports just by declaring it as a function that accepts a number, and returns nothing.