JavaScript to TypeScript | Complete Guide with React ⚛️
SUCHINTAN DAS
Posted on June 19, 2022
Table of Content
➡ Classes
📌 React TypeScript Project Structure
➡ Models
➡ Apis
➡ Pages
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 !
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"
}
]
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"
}
]
Functions
JavaScript 🟡
let func1= (arg1) => {
return "str"
}
let func2 = (arg2) => {
}
TypeScript 🔵
const func1 = (arg1: number): string => {
return "str";
};
const func2 = (arg1: number): void => {
};
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 });
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 });
Classes
JavaScript 🟡
class Check {
a;
b;
}
const ch = new Check();
ch.a = 0;
ch.b = "check-string";
TypeScript 🔵
class Check {
a: number;
b: string;
}
const ch = new Check();
ch.a = 0;
ch.b = "check-string";
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 :
Let's start the React Project with TypeScript Template using the command
npx create-react-app client --template typescript
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
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
}
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
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);
}
};
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
authController.tsx
export const token=localStorage.getItem("idtoken") as string
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
Header.tsx
import React, { useState } from 'react'
import './Header.css'
const Header = () => {
return (
<nav>
<h1>Todo List</h1>
</nav>
)
}
export default Header
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;
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;
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
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
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 🚀
Posted on June 19, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.