Hooks
Hooks are supported in @types/react
from v16.8 up.
useState
Type inference works very well for simple values:
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:
You can also use type assertions if a state is initialized soon after setup and always has a value after:
This temporarily "lies" to the TypeScript compiler that {}
is of type IUser
. You should follow up by setting the user
state โ if you don't, the rest of your code may rely on the fact that user
is of type IUser
and that may lead to runtime errors.
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 / useLayoutEffect
Both of useEffect
and useLayoutEffect
are used for performing side effects and return an optional cleanup function which means if they don't deal with returning values, no types are necessary. 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:
Solution to the above example
useRef
In TypeScript, useRef
returns a reference that is either read-only or mutable, depends on whether your type argument fully covers the initial value or not. Choose one that suits your use case.
Option 1: DOM element ref
To access a DOM element: provide only the element type as argument, and use null
as initial value. In this case, the returned reference will have a read-only .current
that is managed by React. TypeScript expects you to give this ref to an element's ref
prop:
If you are sure that divRef.current
will never be null, it is also possible to use the non-null assertion operator !
:
Note that you are opting out of type safety here - you will have a runtime error if you forget to assign the ref to an element in the render, or if the ref-ed element is conditionally rendered.
Tip: Choosing which HTMLElement
to use
Refs demand specificity - it is not enough to just specify any old `HTMLElement`. If you don't know the name of the element type you need, you can check [lib.dom.ts](https://github.com/microsoft/TypeScript/blob/v3.9.5/lib/lib.dom.d.ts#L19224-L19343) or make an intentional type error and let the language service tell you:Option 2: Mutable value ref
To have a mutable value: provide the type you want, and make sure the initial value fully belongs to that type:
See also
useImperativeHandle
We don't have much here, but this is from a discussion in our issues. Please contribute if you have anything to add!
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.