Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

535
Views
Set types on useState React Hook with TypeScript

I'm migrating a React with TypeScript project to use hooks features (React v16.7.0-alpha), but I cannot figure out how to set typings of the destructured elements.

Here is an example:

interface IUser {
  name: string;
}
...
const [user, setUser] = useState({name: 'Jon'});

I want to force user variable to be of type IUser. My only successful trial, is doing it in two phases: Typing, then initializing:

let user: IUser;
let setUser: any;
[user, setUser] = useState({name: 'Jon'});

But I'm sure there is a better way. Also, setUser should be initialized as a function that takes a IUser as input, and returns nothing.

Also, worth noting that using const [user, setUser] = useState({name: 'Jon'}); without any initialization works fine, but I would like to take advantage of TypeScript to force type checking on init, especially if it depends on some props.

Thanks for your help.

over 4 years ago · Santiago Trujillo
5 answers
Answer question

0

First useState takes a generic, which will be your IUser. If you then want to pass around the second destructured element that is returned by useState you will need to import Dispatch. Consider this extended version of your example that has a click handler:

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

interface IUser {
  name: string;
}

export const yourComponent = (setUser: Dispatch<IUser>) => {

    const [user, setUser] = useState<IUser>({name: 'Jon'});

    const clickHander = (stateSetter: Dispatch<IUser>) => {
        stateSetter({name : 'Jane'});
    }

    return (
         <div>
            <button onClick={() => { clickHander(setUser) }}>Change Name</button>
        </div>
    ) 
}

See this answer.

over 4 years ago · Santiago Trujillo Report

0

Use this

const [user, setUser] = useState<IUser>({name: 'Jon'});

See the Corresponding Type in DefinitelyTyped

over 4 years ago · Santiago Trujillo Report

0

https://fettblog.eu/typescript-react/hooks/

// import useState next to FunctionComponent
    import React, { FunctionComponent, useState } from 'react';
    
    // our components props accept a number for the initial value
    const Counter:FunctionComponent<{ initial?: number }> = ({ initial = 0 }) => {
      // since we pass a number here, clicks is going to be a number.
      // setClicks is a function that accepts either a number or a function returning
      // a number
      const [clicks, setClicks] = useState(initial);
      return <>
        <p>Clicks: {clicks}</p>
        <button onClick={() => setClicks(clicks+1)}>+</button>
        <button onClick={() => setClicks(clicks-1)}>-</button>
      </>
    }
over 4 years ago · Santiago Trujillo Report

0

You could also declare the initial state before and then be able to call it any time you want:

type User = typeof initUser;
const initUser = {name: 'Jon'}
...
const [user, setUser] = useState<User>(initUser);

About I interface prefixes: https://basarat.gitbooks.io/typescript/content/docs/styleguide/styleguide.html#interface

over 4 years ago · Santiago Trujillo Report

0

class Form {
    id: NullNumber = null;
    name = '';

    startTime: NullString = null;
    endTime: NullString = null;

    lunchStart: NullString = null;
    lunchEnd: NullString = null;

    [key: string]: string | NullNumber;
}

export const EditDialog: React.FC = () => {
    const [form, setForm] = useState<Form>(new Form());


    const inputChange = (e: ChangeEvent<HTMLInputElement>) => {
        const element = e.target;
        setForm((form: Form) => {
            form[element.name] = element.value;
            return form;
        })
    }
    return (
        <Box pt={3}>
            <TextField
                required
                name="name"
                label="Наименование"
                defaultValue={form.name}
                onChange={inputChange}
                fullWidth
            />
        </Box>
    );
}
over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!