Hooks
Hooks are supported in @types/react
from v16.8 up.
useState
Type inference works very well most of the time:
See also the Using Inferred Types section if you need to use a complex type that you've relied on inference for.
However, many hooks are initialized with null-ish default values, and you may wonder how to provide types. Explicitly declare the type, and use a union type:
useReducer
You can use Discriminated Unions for reducer actions. Don't forget to define the return type of reducer, otherwise TypeScript will infer it.
View in the TypeScript Playground
Usage with `Reducer` from `redux`
In case you use the redux library to write reducer function, It provides a convenient helper of the format Reducer<State, Action>
which takes care of the return type for you.
So the above reducer example becomes:
useEffect
When using useEffect
, take care not to return anything other than a function or undefined
, otherwise both TypeScript and React will yell at you. This can be subtle when using arrow functions:
useRef
When using useRef
, you have two options when creating a ref container that does not have an initial value:
The first option will make ref1.current
read-only, and is intended to be passed in to built-in ref
attributes that React will manage (because React handles setting the current
value for you).
What is the !
at the end of null!
?
null!
is a non-null assertion operator (the !
). It asserts that any expression before it is not null
or undefined
, so if you have useRef<HTMLElement>(null!)
it means that you're instantiating the ref with a current value of null
but lying to TypeScript that it's not null
.
The second option will make ref2.current
mutable, and is intended for "instance variables" that you manage yourself.
View in the TypeScript Playground
example from Stefan Baumgartner
useImperativeHandle
we dont have much here, but this is from a discussion in our issues
Custom Hooks
If you are returning an array in your Custom Hook, you will want to avoid type inference as TypeScript will infer a union type (when you actually want different types in each position of the array). Instead, use TS 3.4 const assertions:
View in the TypeScript Playground
This way, when you destructure you actually get the right types based on destructure position.
Alternative: Asserting a tuple return type
If you are having trouble with const assertions, you can also assert or define the function return types:
A helper function that automatically types tuples can also be helpful if you write a lot of custom hooks:
Note that the React team recommends that custom hooks that return more than two values should use proper objects instead of tuples, however.
More Hooks + TypeScript reading:
- https://medium.com/@jrwebdev/react-hooks-in-typescript-88fce7001d0d
- https://fettblog.eu/typescript-react/hooks/#useref
If you are writing a React Hooks library, don't forget that you should also expose your types for users to use.
Example React Hooks + TypeScript Libraries: