All you need to know as a Junior React developer getting started with Typescript

All you need to know as a Junior React developer getting started with Typescript

If you have recently applied for a front-end developer job, then you probably noticed that TypeScript is mentioned in almost any job description as a required or nice to have technology.

For newbies that try to break into the tech industry, having to learn yet another programming language might feel overwhelming. But don’t despair, I got you! Although Typescript documentation might look intimidating, there is actually very little you have to know in order to implement it successfully in your React projects.

TypeScript is a superset of JavaScript, whose role is to catch mistakes early, through a type system, and to make JavaScript development more efficient. The cool part is that JavaScript code is valid TypeScript code. You can almost rename your .js files to .ts files and start using TypeScript.

There are tons of articles on why TypeScript makes Javascript code less bug prone, so I’m not going to get into details.

Instead, I will create a sign up form and in the process we will go through the most common use cases that you are likely to encounter in your developer job.

This article is intended for those of you who are already familiar with React and want to start using TypeScript.

Step 1.

As you probably know, Create React App is the fastest way to get you started with a React application. To create our Sign up Form project with TypeScript, you can open your terminal and run:

npx create-react-app ts-form --template typescript
or
yarn create react-app ts-form --template typescript

I chose the app name to be ts-form, but feel free to go with any name you like.

Step 2.

Run the following commands in the terminal to open the app in the browser:

yarn start
or
npm start

cd ts-form

Step 3.

To minimize the CSS code we have to write, we are going to use Material UI, a popular React UI framework:

npm install @mui/material @emotion/react @emotion/styled
or
yarn add @mui/material @emotion/react @emotion/styled

Step 4. Add boilerplate JSX and styling

To get us started, I wrote a little of boilerplate code. Check App.tsx and App.css files.

In App.tsx you can find our root component, App, and a smaller component, Formfield. Formfield component is rendered by App component and each Formfield component represents a text input in our form.

At this point, your app should look something like this:

Screenshot 2021-10-19 at 16.23.48.png

Step 5. Type checking props

Formfield is a reusable component that receives the name as prop. name variable helps us customize the labels in our form.

There are two ways in which we can typecheck a prop.

=> We destructure the variable and declare its type inline, like in the example below:

const Formfield= ({name}: {name: string}) =>  {
  return (
    <div className='textfield-wrapper'>
       <TextField label={name} variant='standard' />
    </div>
  )
}

=> Or we can use types:

type FormfieldPropType = {
  name: string
}

const Formfield= ({name}: FormfieldPropType) =>  {
  return (
    <div className='textfield-wrapper'>
       <TextField label={name} variant='standard' />
    </div>
  )
}

Step 6.

It’s time to get the user’s input and store it in 3 variables: fullName, email and phoneNumber.

Now, every time the user types, we will update our state/the value of our variables. For this, we will use React's built in hook, useState, and from the App component we will pass down to the Fieldtype component the following new props:

=> value, which is going to be of type string

=> onChange, which is going to have a different type

const App = () => {
  const [fullName, setFullName] = useState('')
  const [email, setEmail] = useState('')
  const [phoneNumber, setPhoneNumber] = useState('')


  return (
    <div className='App'>
      <div className='form-wrapper'>
        <div className='form-title'>Create a free account today</div>
        <div className='field-containexr'>
          <Formfield name='Full name' value={fullName} onChange={setFullName}/>
          <Formfield name='Email' value={email} onChange={setEmail} />
          <Formfield name='Phone number'value={phoneNumber} onChange={setPhoneNumber}/>
        </div>
        <div className='button-wrapper'>
        <Button variant='contained'>Sign up</Button>
        </div>
      </div>
    </div>
  );
}
type FormfieldPropType = {
  name: string
  value: string 
  onChange: React.Dispatch<React.SetStateAction<string>>
}

const Formfield= ({name, value, onChange}: FormfieldPropType) =>  {
  return (
    <div className='textfield-wrapper'>
       <TextField label={name} variant='standard' value={value} onChange={(e) => onChange(e.target.value) }/>
    </div>
  )
}

If you don’t know the type of a certain function, like setFullName in my case, all you have to do to find out is to hover over that element.

Screenshot 2021-10-19 at 16.55.23.png

Find here the updated code in App.tsx.

Step 7. Type checking hooks

TypeScript tries to infer the type if you do not specify one, by determining the type of the initial value assigned to it. Let’s take this example:

const [fullName, setFullName] = useState('')

Because we have initialized the fullname variable as an empty string, Typescript correctly inferred our type as string. You can check the type inferred by hovering on the variable.

But there are times when we expect our variable to have a very specific type, in which case Typescript might not know what to infer. Let’s imagine we want to save the response from the server in a variable. And we know that the response will be an object or null.

We can use explicit typing and write the type of our variable. If we expect our variable to be an object or null we will write like this:

const [serverResponse, setServerResponse] = useState<Object | null>(null)

| means or in this case.

We can be even more specific and create a type for our variable. In the example below, we expect our variable to be either null or an object with 2 properties:

=> response, that has the type boolean

=> data, that has the type array of strings

type serverResponseType = {
    response: boolean,
    data: string[]
  }

Example in which we initialize the variable as null:

const [serverResponse, setServerResponse] = useState<serverResponseType | null>(null)

Example in which we initialize the variable as object of type serverResponseType:

const [serverResponse, setServerResponse] = useState<serverResponseType | null>({response: false, data: ['string1', 'string2]})

Step 8. Type checking functions’ input

Next, we will grab the user's input and pretend we save it in a database and return a server response. First we need to create a function that will be executed when we click on the Sign up button.

That function will take an object as an argument, and the object will contain 3 key value pairs. We have done something similar before, at step 5.

We create an interface, then we declare the parameters and the type of that parameters. Below, the function onSignUp, has an Object as a parameter, and the object has 3 properties: fullname, email and phoneNumber.

interface onSignUpProps {
    fullName: string, 
    email: string, 
    phoneNumber: string
}

  const onSignUp = ({fullName, email, phoneNumber}: onSignUpProps) => {
    console.log(fullName, email, phoneNumber)

    return {
      response: true
    }
  }

In real world, onSignUp* would be an async function, but async JavaScript is beyond the scope of this articles.

Interface vs Type

As you've probably noticed, contrasting to the example in step 5, in the previous step I used interface instead of type. Types and interfaces are very similar, and in many cases you can choose freely between them. Feel free to read more about it in the official documentation.

Step 9. Type checking functions’ returned value

For functions, we can type check not only the parameters, but also what the function returns. For example, let’s say that our function, onSignUp will return either an object or null. To type check a function's returned value, all we have to do is to write the type of that value, after the parameters.

In our case, the function onSignUp will return either an object, with response as a key and true/false as value, or null.

 type serverResponseType = {
   response: boolean,
 }

 const onSignUp = ({fullName, email, phoneNumber}: onSignUpProps): serverResponseType | null => {
 console.log(fullName, email, phoneNumber)

  return {
    response: true
  }
}

Find the final version of the code on replit.com.

Step 10. Congratulate yourself! If you have managed to follow the explanations so far, then you’re a 10!

hero_illustration.png