Typing the props and state of React functional components

There are multiple approaches to typing the props and here are two of them.

interface ChildProps {
  color: string;
}

export const Child = ({color}: ChildProps) => {
  return <div>{color}</div>
}
import { Child } from './Child'

const Parent = () => {
  return <Child color="fuchsia" />
}

export default Parent

While this approach is fine and works most of the time, it doesn’t give us all the type benefits we could get because Typescript doesn’t know the component is a React component, it only knows the code is some random JSX that could represent anything.

That means that for example Typescript won’t know about or try to hint about things like Child.defaultProps, Child.displayName, Child.contextTypes etc.

If you want to use these another approach is more suitable.

interface ChildProps {
  color: string;
}

export const Child: React.FC<ChildProps> = ({color}) => {
  return <div>{color}</div>
}

One other advantage of this approach is that now the component can accept children:

interface ChildProps {
  color: string;
}

export const Child: React.FC<ChildProps> = ({color, children}) => {
  return <div>{color}</div>
}
import { Child } from './Child'

const Parent = () => {
  return <Child color="fuchsia">Something to pass as children<Child/>
}

export default Parent

In the simple form TS would not accept the children because that requires an altered type for the component and using React.FC does that for us.

Using generics to type the state

While for some things Typescript can safely infer the type of the state (like the name below which is inferred as a string) for others we need to explicitly set it. That’s where generics can help us again.