Comment écrire un composant React en TypeScript?
Marcos Musafiri

Marcos Musafiri

9/14/2022

Category: App Development

How to write a React component in TypeScript?

In recent years, TypeScript has gained immense popularity among front-end developers. Improved maintainability, code consistency and support for future browsers are some of the reasons for its success. Although many other frameworks and libraries adopt TypeScript by default, React has remained neutral, allowing developers to choose between TypeScript and JavaScript.

In this article, I will discuss creating a React component with Typescript.

Here is our component without types:

  
    const operations = {
      '+': (left, right) => left + right,
      '-': (left, right) => left - right,
      '*': (left, right) => left * right,
      '/': (left, right) => left / right,
    }

    function Calculator({left, operator, right}){
       const result = operations[operator](left, right);
       return (
         div
           code
              {left} {operator} {right} = output{result}/output
           /code
          /div
        );
    }

    const examples = (
      
        Calculator left={1} operator="+" right={2} /
        Calculator left={1} operator="-" right={2} /
        Calculator left={1} operator="*" right={2} /
        Calculator left={1} operator="/" right={2} /
      
    )
  

Now you may notice that we do things a little differently. Maybe you prefer this instead:

  
    const Calculator({left, operator, right})=>(
      div
         code
            {left} {operator} {right} = {' '}
            output{operations[operator](left, right)}/output
         /code
       /div
    );
  

I don’t like implied feedback. This means that you cannot reasonably declare variables or use hooks. So even for simple components, I never follow this approach.

Ok, so maybe you do this:

  
    const Calculator({left, operator, right})=>{
       const result = operations[operator](left, right);
       return (
         div
           code
              {left} {operator} {right} = output{result}/output
           /code
          /div
        );
    }
  

Honestly, it’s fine most of the time. Personally, I prefer the lifting characteristics of function statements rather than function expressions of this type.

All right, let’s add types to that. For the functions, you have to take into account the types that enter and those that exit. Let’s start with the entry: props. To start, let’s take a simple type for props (we’ll improve it later):

  
    type CalculatorProps = {
      left: number;
      operator: string;
      right: number
    }
  

With this, let’s try some options to apply this type to the props object in our React component.

A common method of typing a React component is to use one of the generics that are embedded in `@types/react` (I mean, it’s embedded, right? So what could go wrong?). It is interesting to note that you cannot enter a function statement this way, so we will have to use a function expression:

  
    const Calculator: React.FCCalculatorProps = ({left, operator, right}) => {
      // implementation cut for reasons of brevity
    }
  

It works pretty well, but there are three major problems with this method:

1. Our `Calculator` function now accepts a prop `children`, even if we don’t do anything with it (So it compiles: Calculator left={1} operator="+" right={2}What? /Calculator

2. You can’t use generic. It’s not very common, but it’s a disadvantage.

3. We must use a function expression and cannot use a function statement.

Ok ok, maybe #3 is not a major problem, but #1 is quite significant. There are a few other smaller issues outlined in this great GitHub problem if you want to dive deeper (also see React TypeScript Cheatsheet). Just say not to use `React.FC` (or its longer `React.FunctionComponent` alias)

One of the things I like about React components is that they’re not that special. Here is the definition of a React component:

A React component is a function that returns something that React can display.

Now, according to `@types/react` we are limited to `null` and `JSX.Elements`, but React can also display strings, numbers and boolean. In any case, because a React component is simply a function that returns something that React can display, typing can be as simple as typing functions. You don’t have to do anything special just because it’s React.

So here’s how I typed the props for this component:

  
  function Calculator({left, operator, right }: CalculatorProps){
    // implementation cut for reasons of brevity
  }
  

This method has none of the disadvantages of `React.FC` and is no more complicated than entering arguments for an ordinary function.

Improvement of `CalculatorProps`

Ok, the next part doesn’t have much to do with typing React components, but I thought you’d find it interesting anyway, so skip ahead if it doesn’t. Let’s improve the `CalculatorProps` type. As a reminder, here’s what we have so far:

  
    J'ai pris la liberté de taper chacune de ces fonctions également :
    const operations = {
      '+': (left, right) => left + right,
      '-': (left, right) => left - right,
      '*': (left, right) => left * right,
      '/': (left, right) => left / right,
    }

    type CalculatorProps = {
      left: number;
      operator: string;
      right: number
    }

    function Calculator({left, operator, right}){
       const result = operations[operator](left, right);
       return (
         div
           code
              {left} {operator} {right} = output{result}/output
           /code
          /div
        );
    }
  

I think the `left` and `right` types are fine. It is `operator` that is not suitable for me. Using `string` is too broad. There are specific operations that are allowed. For example, what would happen if you tried:

  
    const element = Calculator left={1} operator="wut" right={2} /
  

This is called an execution exception my friends. That is... unless you have enabled `strict` mode, in which case you would have a build error on `operations[operator]`. In strict mode, TypeScript will know correctly that access to any string in the `operations` object will not necessarily return a callable function.

There are many ways to solve this problem. Basically, we want to limit Operator` to supported operators only. We can do this with a simple type of union:

  
    type CalculatorProps = {
      left: number;
      operator: '+' | '-' | '*' | '/';
      right: number
    }
  

But if we decide to add Exponentiation Operator (`**`), we should update not only the `operations` object, but also the `operator` type, which would be annoying. Perhaps there is a way to derive the `Operator` type from the `Operations` object? Yes, there is!

  
    type CalculatorProps = {
      left: number;
      operator:  keyof typeof operations;
      right: number
    }
  

`typeof operations` will allow us to obtain a type that describes the `operations` object, which is roughly equal to:

  
    type operations = {
      '+': (left: number, right: number) => number;
      '-': (left: number, right: number) => number;
      '*': (left: number, right: number) => number;
      '/': (left: number, right: number) => number
    }
  

The `keyeof` portion will take all keys of this type, resulting in '+' | '-' | '*' | '/'

Conclusion

Here is the completed version (I also typed the operations functions):

  
    type operations = {
      '+': (left: number, right: number) : number => left + right;
      '-': (left: number, right: number) : number => left - right;
      '*': (left: number, right: number) : number => left * right;
      '/': (left: number, right: number) : number => left / right
    }

    type CalculatorProps = {
      left: number;
      operator:  keyof typeof operations;
      right: number
    }

    function Calculator({left, operator, right }: CalculatorProps){
       const result = operations[operator](left, right);
       return (
         div
           code
              {left} {operator} {right} = output{result}/output
           /code
          /div
        );
     }

     const examples = (
      
        Calculator left={1} operator="+" right={2} /
        Calculator left={1} operator="-" right={2} /
        Calculator left={1} operator="*" right={2} /
        Calculator left={1} operator="/" right={2} /
      
    )
  

I hope this gives you a good idea of how to type your React components. Good luck and take care!

Get in Touch .

Let's discuss how Zabibu can help you achieve your business goals.