React types you didn’t know

After working in several companies, I’ve noticed that the code is always typed differently and this can lead to some issues with typings in the future.

I want to show you how to make code better typed the way you probably didn’t know.

Functi…


This content originally appeared on DEV Community and was authored by Mikhail Grechka

After working in several companies, I've noticed that the code is always typed differently and this can lead to some issues with typings in the future.

I want to show you how to make code better typed the way you probably didn't know.

Function Component type

First of all, we have to figure out what is the best way to define a function component.

Usually developers do initialise components using default functions so the code would look like this:

function SomeComponent(props: SomeComponentProps): JSX.Element {
   ...
}

Such approach has several disadvantages:

  • You always need to write the return type
  • If your component accepts any children you need to define the children property in your Props type and set the type union type like null | ReactNode | ReactNode[] or null | ReactElement – Since you need to use one of types above for your children, you have to import them too

All of these problems make your code more "boilerplaty" and make your code less readable spending more time than you can.

The best solution for this is FC or FunctionComponent types. FC is just a shorthand for FunctionComponent – You can check this here:

type FC<P = {}> = FunctionComponent<P>;

Let's see what this FunctionComponent is:

interface FunctionComponent<P = {}> {
    (props: PropsWithChildren<P>, context?: any): ReactElement<any, any> | null;
    propTypes?: WeakValidationMap<P> | undefined;
    contextTypes?: ValidationMap<any> | undefined;
    defaultProps?: Partial<P> | undefined;
    displayName?: string | undefined;
}

Here we also need to check the PropsWithChildren type to make sure what we will pass to the component's props:

type PropsWithChildren<P> = P & { children?: ReactNode };

Now let's see how FC-typed component looks like:

const SomeComponent: FC<SomeComponentProps> = ({ message }) => (
  <div>{message}</div>
);

Current solution solves such problems:

  • We don't need to define children¹ type anymore
  • We separate values from types moving generic type to the beginning making the code more readable
  • We don't need to write a function return type
  • Since we are using arrow function², we can omit curly braces in some cases and return jsx directly
  • Using the same component type everywhere we prevent inconsistency of types that can lead to waste of time because of type definition instead of spending it to solve actual problems

1 - Keep in mind that it is planned to remove children as default property from FunctionComponent in @types/react@^18.0.0
2 – If you are using React Developer Tools you should notice that arrow functions don't have displayName by default so you should define it manually:

SomeComponent.displayName = 'SomeComponent';

Type of regular HTML props / attributes

You've probably had problems with props definition for components that pass most of their props further to the regular html element.

Previously I've seen solutions like importing HTMLAttributes from react module and then passing HTML...Element type to it as a generic argument:

type SomeType = HTMLAttributes<HTMLInputElement>;

This type is not much reusable because we cannot get props of the custom component and this is where ComponentProps comes:

 // regular HTML input element
type InputElementProps = ComponentProps<'input'>;

// ComponentProps works for both regular elements and the custom ones
type CustomInputProps = ComponentProps<typeof CustomInput>;

CSS property type

If you use css-in-js solutions, sometimes you want your component to accept certain CSS-properties passed deeper to the component's styles.

You can just set the property type as a type union: number | string but it is unspecific and can lead to unpredicted behaviour because of typos when using such properties as position, flex-direction, etc.

The better solution is to use CSSProperties type exported from react module:

interface SomeComponentProps {
  display: CSSProperties['display']
}

Such little things may improve the quality of your code and prevent you from having pain with Typescript.


This content originally appeared on DEV Community and was authored by Mikhail Grechka


Print Share Comment Cite Upload Translate Updates
APA

Mikhail Grechka | Sciencx (2021-09-08T20:55:38+00:00) React types you didn’t know. Retrieved from https://www.scien.cx/2021/09/08/react-types-you-didnt-know/

MLA
" » React types you didn’t know." Mikhail Grechka | Sciencx - Wednesday September 8, 2021, https://www.scien.cx/2021/09/08/react-types-you-didnt-know/
HARVARD
Mikhail Grechka | Sciencx Wednesday September 8, 2021 » React types you didn’t know., viewed ,<https://www.scien.cx/2021/09/08/react-types-you-didnt-know/>
VANCOUVER
Mikhail Grechka | Sciencx - » React types you didn’t know. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2021/09/08/react-types-you-didnt-know/
CHICAGO
" » React types you didn’t know." Mikhail Grechka | Sciencx - Accessed . https://www.scien.cx/2021/09/08/react-types-you-didnt-know/
IEEE
" » React types you didn’t know." Mikhail Grechka | Sciencx [Online]. Available: https://www.scien.cx/2021/09/08/react-types-you-didnt-know/. [Accessed: ]
rf:citation
» React types you didn’t know | Mikhail Grechka | Sciencx | https://www.scien.cx/2021/09/08/react-types-you-didnt-know/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.