Type React with TypeScript — Learn TypeScript Training
In this chapter we will see how to use the react types @types/react
.
00:48 Config tsconfig.json
02:24 Typing props
07:05 Type useState
09:51 Type useRef
11:46 The events
12:52 forwardRef
14:31 Type ReactNode
16:54 Type a component
18:43 Type a context
The configuration
React does not include default types and we will start by installing @types/react
and we will modify the configuration the jsx key in the file tsconfig.json
.
{
"jsx": "react-jsx"
}
This configuration allows to replace the jsx by a call to the jsx function of react/jsx-runtime
.
import { jsx as _jsx } from "react/jsx-runtime";
import React from 'react';
export const HelloWorld = () => _jsx("h1", { children: "Hello world" });
Type a component
By default a function that returns JSX will be considered a component.
type Props: {
start: number
}
function Counter ({start}: Props) {
return <div>Hello World</div>
}
If your component can receive children, then you can use the type PropsWithChildren
type Props: PropsWithChildren<{
start: number
}>
It is also possible to be more explicit by using the type FunctionComponent
this type can be interesting for higher order component returns.
type Props: {
start: number
}
const Counter: FunctionComponent<Props> = ({start}) => {
return <div>Hello World</div>
}
The hooks
The hooks can be used with a generic to indicate the type of value they will handle, but it is inferred from the base by the parameters.
const [n, setN] = useState(3) // Le type sera automatiquement un nombre
const [i, setI] = useState<number>() // Le type sera number | undefined
For the ref it will be necessary to think of putting a null value by default so that it can be included in the prop ref
const ref = useRef<HTMLButtonElement>(null)
You can also use the type RefObject<T>
to represent an object of type ref.
forwardRef
The method forwardRef
it also contains 2 generics to define the format of the props and the ref.
export const Counter = forwardRef<HTMLButtonElement, Props>(({start, children}, ref) => {
// ....
})
Type components
You have several types that are interesting to know depending on certain situations.
ReactNode
allows to represent a node (a piece of JSX, a chain, null or undefined)JSX.IntrinsicElements
is an internal type that allows to represent all HTML elements accepted by React. One can for example usekeyof JSX.IntrinsicElements
if you want a prop to accept an HTML tag.ComponentType<Props>
represents a component (a function or a class) that can be used as a JSX element. You can add a generic to define the props that are expected
The context
For the contexts, 2 situations generally arise.
Context with default state
In this case the type will automatically be inferred from the object that will be used in the default state. We will not hesitate to use as
in order to have the most precise type possible.
const CounterContext = createContext({
n: 0,
incrementer: (step: number) => void,
type: 'card' as 'card' | 'text'
})
export const CounterProvider = () => {
const [n, setN] = useState(0)
const incr = useCallback(() => setN(n => n+1), [])
return <CounterContext.Provider value={{n, incr, type: 'card'}}>
{children}
</CounterContext.Provider>
}
export const useCounter = () => {
return useContext(CounterContext);
}
The checks will then be done automatically:
- In the CounterProvider, the value must have the same form as the object passed as a parameter of
createContext
- the
useContext
will return an object that will have the same shape as the object passed as a parameter ofcreateContext
Default stateless context
In this case we will use a type to define the form of the values within our context and we will use a generic when using createcontext()
type ContextProps = {
n: number,
incr: () => void
}
const CounterContext = createContext<null | ContextProps>(null)
In order to avoid problems when using this context, we will make sure to put an explicit error.
export const useCounter = () => {
const value = useContext(CounterContext);
if (value === null) {
throw new Error('Vous devez entourer ce composant d\'un <CounterProvider>')
}
return value;
}