JavaScript to TypeScript | Complete Guide with React ⚛️

suchintan

SUCHINTAN DAS

Posted on June 19, 2022

JavaScript to TypeScript | Complete Guide with React ⚛️

Table of Content


📌 Introduction

📌 Introduction to TypeScript

Variables

Functions

Multiple Types

Classes

📌 React TypeScript Project Structure

Models

Apis

Components

Pages

📌 Thank you


Introduction

Hello amazing developer 🧑‍💻, before digging into this topic let me give you a small introduction and so instructions. Don't worry it would be quick and crisp.

I am Suchintan Das, a Full Stack Developer currently working over two startups. I have been into web development for past two years.

Connect me on 👉 Linkedin

The whole syntaxes and code are uploaded on this 👉 Repository . If you find it useful , you can star the repository to show a appreciation. Thanks !


Introduction to TypeScript

I know most of you guys who are reading this blog are either not familiar with TypeScript or have a little knowledge about TypeScript as a whole. Don't worry in this whole blog we are going to cover every single thing from the start to bottom and even if you are new to TypeScript you can build a good project easily along with React.

Let's first understand some important syntaxes of TypeScript !

I will be explaining the syntaxes considering that you are coming from JavaScript background and have knowledge about the syntaxes of the same !

Yes Meme


Variables

JavaScript 🟡


let a = "check";
let b= 2;
let c= {
    h: "element"
};
let d= [1,2,3];
let e= false;
let f= ["check",2]
let g= c.h;
let i=null
let j=undefined
let k= [
    {
        h:"element1"
    }
]

Enter fullscreen mode Exit fullscreen mode

TypeScript 🔵


let a: string = "check";

let b: number = 2;

interface ctype {
    h:string
}
let c: ctype = {
  h: "element",
};

let d: Array<number> = [1, 2, 3];

let e: boolean = false;

let f: [string, number] = ["check", 2]; //tuple

let g: string = c.h;

let h: unknown = "noideaabout"; //a variable whose type is not known it could be a string, object, boolean, undefined, or other types but not number

let i:null=null

let j:undefined=undefined

let k: Array<ctype> = [
    {
        h:"element1"
    }
]


Enter fullscreen mode Exit fullscreen mode


Functions

JavaScript 🟡


let func1= (arg1) => {
    return "str"
}

let func2 = (arg2) => {

}

Enter fullscreen mode Exit fullscreen mode

TypeScript 🔵


const func1 = (arg1: number): string  => {
    return "str";
};


const func2 = (arg1: number): void  => {

};

Enter fullscreen mode Exit fullscreen mode


Multiple Types

JavaScript 🟡


function randomfunc(arg) {
    // ...
  }
  randomfunc({ shape:"check1" });
  randomfunc({ shape:undefined, xPos: 100 });
  randomfunc({ shape:2, yPos: 100 });
  randomfunc({ shape:"check1", xPos: 100, yPos: 100 });

Enter fullscreen mode Exit fullscreen mode

TypeScript 🔵


interface typeOptions {
    shape: string | undefined | number;  //multiple types to same parameter
    xPos?: number;  //optional parameters
    yPos?: number;  //optional parameters
  }
function randomfunc(arg: typeOptions) {
    // ...
  }
  randomfunc({ shape:"check1" });
  randomfunc({ shape:undefined, xPos: 100 });
  randomfunc({ shape:2, yPos: 100 });
  randomfunc({ shape:"check1", xPos: 100, yPos: 100 });

Enter fullscreen mode Exit fullscreen mode


Classes

JavaScript 🟡


class Check {
    a;
    b;
  }

const ch = new Check();
ch.a = 0;
ch.b = "check-string";


Enter fullscreen mode Exit fullscreen mode

TypeScript 🔵


class Check {
    a: number;
    b: string;
  }

const ch = new Check();
ch.a = 0;
ch.b = "check-string";

Enter fullscreen mode Exit fullscreen mode


Now that we are familiar with all the syntaxes of TypeScript we can now dive into React with TypeScript full project setup.

Let's go !


React TypeScript Project Structure


Here's a small peak to the Project :

Project Peak

Let's start the React Project with TypeScript Template using the command


npx create-react-app client --template typescript

Enter fullscreen mode Exit fullscreen mode

Note: To explain the whole structure I will be making a todo list project so that everyone can get an idea how to implement the same on any other project or product.


React TypeScript with Project


Models

Models

ITask.ts


export interface Tasks {
    id: number,
    title: string,
    content: string
}

export interface TaskList extends Array<Tasks>{}

export interface TasksProps {
    d: TaskList | undefined,
    changed: Function
  }

Enter fullscreen mode Exit fullscreen mode

Here's you can see for this project there are 3 interfaces that I used. First interface Tasks is description of elements of the Array of Objects and the second interface TaskList is the declaration of array of the interface Tasks.

Thirdly there is another interface TasksProps which is used here to describe all the props typing while passed between components.


Apis

Api's

Task.ts


import axios          from "axios";
import { TaskList, Tasks } from "../../models/ITask";
import { token } from "../../utils/authController";

const baseUrl = "http://localhost:5000";


//receive tasks
export const getTasks = async () => {
    try {
        const response = await axios.get(
            baseUrl + '/tasks/gettasks', { headers: { 'Authorization': `bearer ${token}`, } });
        return response.data as TaskList;
    } catch (e) {
        console.log(e);
    }
};

//add tasks
export const postTasks = async (data:Tasks) => {
    try {
        const response = await axios.post(
            baseUrl + '/tasks/addtasks', data, { headers: { 'Authorization': `bearer ${token}`, } });
        return response.status as number;
    } catch (e) {
        console.log(e);
    }
};

Enter fullscreen mode Exit fullscreen mode

Here I have used axios for making backend calls. The preference can go different for you ! The main idea here is to make a typing of arguements and return types each function would be having so that any developer can make a call in the right syntax and do get the desired form of response body.


Controllers

Controllers

authController.tsx


export const token=localStorage.getItem("idtoken") as string

Enter fullscreen mode Exit fullscreen mode

Controllers are an essential element for frontend developers. Things which decide the flow of the website , are mostly the controllers of a website. Like here the authentication part is put into the controllers as it would be a flow decider for mostly all the components.


Components

Components

Header.tsx


import React, { useState } from 'react'
import './Header.css'

const Header = () => {
  return (
    <nav>
      <h1>Todo List</h1>
    </nav>
  )
}

export default Header

Enter fullscreen mode Exit fullscreen mode

TaskInput.tsx


import React, { useState, useEffect } from "react";
import { postTasks } from "../../apis/Tasks/Task";
import { TasksProps } from "../../models/ITask";
import Home from "../../pages/Home/Home";
import "./TaskInput.css";

export const TaskInput: React.FC<TasksProps> = ({ d, changed }: TasksProps) => {
  //states
  const [callapi, setcallapi] = useState<Boolean>(false);
  const [sendd, setsendd] = useState<Boolean>(false);
  const [content, setcontent] = useState<string>("");
  const [title, settitle] = useState<string>("");

  console.log("TaskInput")
  console.log(d)

  //api-call
  useEffect(() => {
    const senddata = () => {
      postTasks({id:d?.length!+1, title: title, content: content})
        .then((res) => {
          if (res === 200) {
            let updatedata: Array<Object> | undefined = d;
            updatedata?.push({
              id: d?.length! + 1,
              title: title,
              content: content,
            });
            console.log(updatedata)
            changed(updatedata);
          }
        })
        .catch((error) => {
          console.log(error);
        });
    };

    if(sendd)
    {
      senddata();
      changed([]);
    }
  }, [callapi]);

  return (
    <div className="taskinput">
      <h1>Add Tasks</h1>
      <input type="text" placeholder="title" onChange={(event)=> {
          settitle(event?.target?.value)
        }}/>
      <textarea
        name="content"
        id=""
        cols={20}
        rows={10}
        placeholder="content"
        onChange={(event)=> {
          setcontent(event?.target?.value)
        }}
      ></textarea>
      <div className="add">
        <button onClick={()=> {
          setsendd(true);
          callapi ? setcallapi(false) : setcallapi(true);
        }}>Add</button>
        <i className="fa-solid fa-plus"></i>
      </div>
    </div>
  );
};

export default TaskInput;

Enter fullscreen mode Exit fullscreen mode

Tasks.tsx


import React, { useEffect, useState } from "react";
import { getTasks } from "../../apis/Tasks/Task";
import { TaskList, TasksProps } from "../../models/ITask";
import "./Tasks.css";

export const Tasks: React.FC<TasksProps> = ({ d, changed }: TasksProps) => {
  //states
  const [callapi, setcallapi] = useState<Boolean>(false);

  console.log("Tasks")
  console.log(d)


  //api-call
  useEffect(() => {
    const receivedata = () => {
      getTasks()
        .then((res) => {
          changed(res);
        })
        .catch((error) => {
          console.log(error);
        });
    };

    receivedata();
  }, [callapi]);

  return (
    <div className="tasks">
      {d?.map((ele) => {
        return ele !== null ? (
          <div className="task" key={ele.id}>
            <h1>{ele?.title}</h1>
            <p>{ele?.content}</p>
          </div>
        ) : (
          null
        );
      })}
    </div>
  );
};

export default Tasks;

Enter fullscreen mode Exit fullscreen mode

Here's a small summary of all the components . TaskInput component is sent two props whose typing are already been declared on models . The props are the states sent from parent component Home.tsx to TaskInput.tsx and Tasks.tsx so any changes in any of the child component gets reflected on the other component.

The api calls also have been declared already and the function call is made from the components for the data.


Pages

Pages

Home.tsx


import React, { useState } from 'react'
import Header from '../../components/Header/Header'
import TaskInput from '../../components/TaskInput/TaskInput'
import Tasks from '../../components/Tasks/Tasks'
import { TaskList } from '../../models/ITask'
import './Home.css'

const Home = () => {
  const [data, setdata] = useState<TaskList|undefined>([]);
  return (
    <>
    <Header/>
    <div className="dashboard">
      <TaskInput d={data} changed={setdata}/>
      <Tasks d={data} changed={setdata}/>
    </div>
    </>
  )
}

export default Home

Enter fullscreen mode Exit fullscreen mode

The states for data are declared on the parent component and sent as props to child components to make data changes on any child components reflect back to the other child.

It's possible as the pointer to the state is sent to the childrens.


Thank you

You have made it till the end of this blog 🤗. More such blogs are on the line .

It would be encouraging if a small comment would be there on the blog. I go through each one of them so do comment 😉.

If you want to get a notification 🔔 when it would be published , don't forget to tap on the follow button ☝.

And at last I want to say 👇

Keep coding #️⃣ , keep rocking 🚀

💖 💪 🙅 🚩
suchintan
SUCHINTAN DAS

Posted on June 19, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related