Type inference from React.useState
David Johnston
Posted on September 29, 2020
The Problem
import React from "react";
const Foo = () => {
const [value, setValue] = React.useState();
return <input value = {value} onChange = {(e) => setValue(e.target.value)}/>
}
This code produces the following TypeScript error:
Argument of type 'string' is not assignable to parameter of type 'SetStateAction<undefined>'.(2345)
Quick Solution
Explicitly state the generic type:
import React from "react";
const Foo = () => {
const [value, setValue] = React.useState<string | undefined>();
return <input value = {value} onChange = {(e) => setValue(e.target.value)}/>
}
Or set the initial state to an empty string.
import React from "react";
const Foo = () => {
const [value, setValue] = React.useState('');
return <input value = {value} onChange = {(e) => setValue(e.target.value)}/>
}
(This may not be appropriate for all cases, ie maybe you really do want to leave that value undefined).
Explanation
The useState
function has a generic parameter which we are not setting/declaring in the original case.
This leaves TypeScript to infer the generic type from the arguments given.
In this case useState()
with no arguments, TypeScript infers the type as undefined
.
TypeScript doesn't know that you later want to set a string into state here.
That is, leaving the generic parameter off is equivalent of doing:
const [value, setValue] = React.useState<undefined>();
The generic parameter determines the type of the value
and setValue
variables.
In this case, the setValue
function is going to be the equivalent of:
function setValue(value: undefined) : void {
}
The input
component doesn't like this, the event is creating has a target.value
of type string
.
So to solve this, we can either explicitly set the generic type, or be aware of when and how TypeScript is going to infer the generic type.
Posted on September 29, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 23, 2024
November 16, 2024