Thanks to visit codestin.com
Credit goes to www.scribd.com

0% found this document useful (0 votes)
12 views36 pages

Typescript Tutorial ChatGPT

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
12 views36 pages

Typescript Tutorial ChatGPT

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 36

Typescript Tutorial (_ChatGPT)

Introduction
Why TypeScript?
The Evolution of JavaScript and the Need for TypeScript
Setting Up Your Environment
Basic Syntax and Concepts

Part 1: Getting Started with TypeScript


1. Introduction to TypeScript
What is TypeScript?
Advantages of TypeScript
TypeScript vs. JavaScript
2. Setting Up TypeScript
Installing TypeScript
Configuration and the tsconfig.json File
3. Basic Types
Primitive Types
Arrays and Tuples
Enums
4. Functions
Function Types
Optional and Default Parameters
Rest Parameters
5. Interfaces and Classes
Defining Interfaces
Implementing Interfaces
Classes and Inheritance
6. Advanced Types
Union and Intersection Types
Type Guards
Literal Types and Type Aliases

Part 2: Intermediate Concepts


7. Generics
Introduction to Generics
Generic Functions and Classes
Generic Constraints
8. Decorators
What are Decorators?
Method, Class, and Property Decorators
9. Namespaces and Modules
Organizing Code with Namespaces
ES6 Modules and TypeScript
10. TypeScript with React
Setting Up a React Project with TypeScript
Typing React Components and Props
Context API and Hooks with TypeScript

Part 3: Advanced Projects


11. Building a REST API with TypeScript and Node.js
Setting Up the Project
Creating Models and Controllers
Middleware and Error Handling
Testing the API
12. Real-Time Applications with TypeScript and Socket.io
Setting Up a Real-Time Server
Handling Events and Broadcasting
Integrating with a Front-End
13. TypeScript with GraphQL
Setting Up a GraphQL Server
Defining Schemas and Resolvers
Integrating with a Front-End
14. Full-Stack Application with TypeScript
Setting Up the Front-End and Back-End
Connecting Front-End and Back-End
Authentication and Authorization
Deployment

Conclusion
Best Practices for TypeScript
Resources for Further Learning
Final Thoughts

Introduction

Why TypeScript?
TypeScript is a powerful, statically typed superset of JavaScript that brings the power of static
typing and object-oriented programming to the world of JavaScript development. As JavaScript
projects grow in size and complexity, maintaining and debugging code becomes more
challenging. This is where TypeScript shines. It helps developers catch errors early, improves
code quality, and enhances the overall development experience.

The Evolution of JavaScript and the Need for TypeScript


JavaScript, initially designed for simple web interactivity, has evolved into a language capable of
powering large-scale, complex applications. However, as JavaScript applications scale, the lack of
static typing and modern language features can lead to maintainability and scalability issues.
TypeScript addresses these problems by introducing static types, interfaces, and advanced
language features, making JavaScript development more robust and efficient.

Setting Up Your Environment


Before diving into TypeScript, it's essential to set up your development environment. This
includes installing Node.js, TypeScript, and a code editor like Visual Studio Code.

Step 1: Install Node.js Download and install Node.js from the official website nodejs.org.
Node.js comes with npm, which will be used to install TypeScript and other dependencies.

Step 2: Install TypeScript Open your terminal and run the following command to install
TypeScript globally:

npm install -g typescript

Step 3: Verify the Installation After installation, verify that TypeScript is installed by running:

tsc --version
Step 4: Set Up Visual Studio Code Download and install Visual Studio Code from
code.visualstudio.com. It's a powerful code editor with excellent TypeScript support.

Basic Syntax and Concepts


Let's start with a simple TypeScript program. Create a new file called hello.ts and add the
following code:

function greet(name: string): string {


return `Hello, ${name}!`;
}

const user = 'World';


console.log(greet(user));

To compile this TypeScript code to JavaScript, run:

tsc hello.ts

This will generate a hello.js file. You can run this file with Node.js:

node hello.js

Sample Chapter: Chapter 5 - Interfaces and Classes

Interfaces
Interfaces in TypeScript are a powerful way to define contracts within your code. They can define
the shape of an object, ensuring that an object meets certain criteria.

Defining Interfaces

Here's how you can define and use an interface:


interface User {
name: string;
age: number;
}

function printUser(user: User): void {


console.log(`Name: ${user.name}, Age: ${user.age}`);
}

const user: User = {


name: 'Alice',
age: 25
};

printUser(user);

Optional Properties

Interfaces can also have optional properties, indicated by a ? :

interface User {
name: string;
age?: number;
}

const user: User = {


name: 'Bob'
};

printUser(user); // No age provided

Classes
Classes in TypeScript provide a way to define blueprints for creating objects with specific
properties and methods.

Defining a Class

Here's a simple class example:


class Person {
name: string;
constructor(name: string) {
this.name = name;
}

greet(): string {
return `Hello, my name is ${this.name}`;
}
}

const person = new Person('Charlie');


console.log(person.greet());

Inheritance

TypeScript supports class inheritance using the extends keyword:

class Employee extends Person {


position: string;
constructor(name: string, position: string) {
super(name);
this.position = position;
}

describe(): string {
return `${this.name} works as a ${this.position}`;
}
}

const employee = new Employee('David', 'Developer');


console.log(employee.describe());

Implementing Interfaces
Classes can implement interfaces to ensure they adhere to a specific contract:
interface Drivable {
startEngine(): void;
stopEngine(): void;
}

class Car implements Drivable {


startEngine(): void {
console.log('Engine started');
}

stopEngine(): void {
console.log('Engine stopped');
}
}

const car = new Car();


car.startEngine();
car.stopEngine();

Conclusion
In this chapter, we've explored the basics of interfaces and classes in TypeScript. These powerful
features help you define clear contracts and reusable blueprints for your objects, making your
code more robust and maintainable. In the next chapter, we'll dive into advanced types and how
they can further enhance your TypeScript code.

Sure, let's continue by expanding on the next chapters to provide more content and structure.
I'll extend the previous chapters and introduce more chapters to create a comprehensive
learning experience for TypeScript.

Chapter 6: Advanced Types

Union and Intersection Types


TypeScript provides powerful features to combine types. Union types allow a value to be one of
several types, while intersection types combine multiple types into one.

Union Types
Union types are used when a value can be one of several types:

function printId(id: number | string) {


console.log(`ID: ${id}`);
}

printId(101);
printId("202");

Intersection Types

Intersection types combine multiple types into one:

interface Person {
name: string;
}

interface Employee {
employeeId: number;
}

type Staff = Person & Employee;

const staffMember: Staff = {


name: 'Alice',
employeeId: 1234
};

Type Guards
Type guards allow you to narrow down the type within a union type using specific checks.

Using typeof

function printValue(value: number | string) {


if (typeof value === 'string') {
console.log(`String value: ${value}`);
} else {
console.log(`Number value: ${value}`);
}
}
Using instanceof

class Car {
drive() {
console.log('Driving a car');
}
}

class Truck {
tow() {
console.log('Towing a truck');
}
}

function operate(vehicle: Car | Truck) {


if (vehicle instanceof Car) {
vehicle.drive();
} else {
vehicle.tow();
}
}

Literal Types and Type Aliases


Literal types allow you to specify exact values a type can have, and type aliases provide a way to
name complex types.

Literal Types

type Direction = 'north' | 'south' | 'east' | 'west';

function move(direction: Direction) {


console.log(`Moving ${direction}`);
}

move('north');

Type Aliases
type User = {
name: string;
age: number;
};

const user: User = {


name: 'Bob',
age: 30
};

Chapter 7: Generics
Generics provide a way to create reusable components that work with any data type.

Generic Functions
Generic functions allow you to write functions that can work with any type:

function identity<T>(arg: T): T {


return arg;
}

console.log(identity<number>(10));
console.log(identity<string>('Hello'));

Generic Classes
Generic classes work similarly to generic functions:
class Box<T> {
contents: T;
constructor(contents: T) {
this.contents = contents;
}

getContents(): T {
return this.contents;
}
}

const numberBox = new Box<number>(123);


console.log(numberBox.getContents());

const stringBox = new Box<string>('Hello');


console.log(stringBox.getContents());

Generic Constraints
Generic constraints allow you to limit the kinds of types that a generic type parameter can
accept:

interface Lengthwise {
length: number;
}

function logLength<T extends Lengthwise>(item: T): void {


console.log(item.length);
}

logLength('Hello');
logLength([1, 2, 3]);

Chapter 8: Decorators
Decorators provide a way to add metadata to classes, methods, properties, and parameters.

Method Decorators
Method decorators can be used to modify or annotate methods:
function log(target: any, propertyName: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = function(...args: any[]) {
console.log(`Calling ${propertyName} with arguments: ${args}`);
return originalMethod.apply(this, args);
}
}

class Calculator {
@log
add(a: number, b: number): number {
return a + b;
}
}

const calculator = new Calculator();


calculator.add(2, 3);

Class Decorators
Class decorators can be used to add metadata to classes:

function sealed(constructor: Function) {


Object.seal(constructor);
Object.seal(constructor.prototype);
}

@sealed
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}

greet() {
return `Hello, ${this.greeting}`;
}
}

Property Decorators
Property decorators can be used to add metadata to properties:
function logProperty(target: any, key: string) {
let value = target[key];

const getter = () => {


console.log(`Get: ${key} => ${value}`);
return value;
};

const setter = (newVal: any) => {


console.log(`Set: ${key} => ${newVal}`);
value = newVal;
};

Object.defineProperty(target, key, {
get: getter,
set: setter,
enumerable: true,
configurable: true
});
}

class Person {
@logProperty
name: string;

constructor(name: string) {
this.name = name;
}
}

const person = new Person('Alice');


person.name = 'Bob';
console.log(person.name);

Chapter 9: Namespaces and Modules


Namespaces and modules help in organizing and managing code in TypeScript.

Namespaces
Namespaces are used to organize code into logical groups and prevent name collisions.
Defining and Using Namespaces

namespace Utility {
export function log(message: string): void {
console.log(message);
}

export function error(message: string): void {


console.error(message);
}
}

Utility.log('This is a log message');


Utility.error('This is an error message');

Modules
Modules in TypeScript align with the ES6 module system and are used to organize code into
separate files and modules.

Exporting and Importing Modules

File: math.ts

export function add(a: number, b: number): number {


return a + b;
}

export function subtract(a: number, b: number): number {


return a - b;
}

File: main.ts

import { add, subtract } from './math';

console.log(add(10, 5));
console.log(subtract(10, 5));

Chapter 10: TypeScript with React


React is a popular JavaScript library for building user interfaces. TypeScript can be integrated
with React to provide type safety and better tooling.

Setting Up a React Project with TypeScript


Create a new React project with TypeScript using Create React App:

npx create-react-app my-app --template typescript


cd my-app
npm start

Typing React Components


Typing functional and class components in React with TypeScript.

Functional Components

import React from 'react';

interface Props {
message: string;
}

const Greeting: React.FC<Props> = ({ message }) => {


return <h1>{message}</h1>;
};

export default Greeting;

Class Components
import React, { Component } from 'react';

interface Props {
message: string;
}

class Greeting extends Component<Props> {


render() {
return <h1>{this.props.message}</h1>;
}
}

export default Greeting;

Context API and Hooks with TypeScript


Using Context API and hooks in a TypeScript environment.

Using Context API


import React, { createContext, useContext } from 'react';

interface UserContextType {
name: string;
age: number;
}

const UserContext = createContext<UserContextType | null>(null);

const UserProvider: React.FC = ({ children }) => {


const user = { name: 'Alice', age: 25 };
return <UserContext.Provider value={user}>{children}</UserContext.Provider>;
};

const UserProfile: React.FC = () => {


const user = useContext(UserContext);
if (!user) {
return <div>Loading...</div>;
}
return <div>Name: {user.name}, Age: {user.age}</div>;
};

const App: React.FC = () => (


<UserProvider>
<UserProfile />
</UserProvider>
);

export default App;

Using Hooks
import React, { useState } from 'react';

const Counter: React.FC = () => {


const [count, setCount] = useState<number>(0);

return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
};

export default Counter;

Absolutely, let's continue with the advanced project chapters. We'll dive into building a REST API
with TypeScript and Node.js, creating real-time applications with Socket.io, working with
GraphQL, and building a full-stack application.

Chapter 11: Building a REST API with TypeScript and


Node.js

Setting Up the Project


To get started, create a new project directory and initialize a Node.js project:

mkdir rest-api
cd rest-api
npm init -y

Install the necessary dependencies:

npm install express body-parser mongoose


npm install -D typescript @types/node @types/express @types/body-parser
@types/mongoose ts-node nodemon

Create a tsconfig.json file to configure TypeScript:


{
"compilerOptions": {
"target": "ES6",
"module": "commonjs",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true
},
"include": ["src"],
"exclude": ["node_modules"]
}

Creating Models and Controllers


Create a new src directory and add the following structure:

src/
models/
user.ts
controllers/
userController.ts
routes/
userRoutes.ts
app.ts
server.ts

Defining the User Model

File: src/models/user.ts
import mongoose, { Document, Schema } from 'mongoose';

export interface IUser extends Document {


name: string;
email: string;
password: string;
}

const userSchema: Schema = new Schema({


name: { type: String, required: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true }
});

export default mongoose.model<IUser>('User', userSchema);

Creating the User Controller

File: src/controllers/userController.ts

import { Request, Response } from 'express';


import User, { IUser } from '../models/user';

export const createUser = async (req: Request, res: Response): Promise<void> => {
try {
const { name, email, password } = req.body;
const user: IUser = new User({ name, email, password });
await user.save();
res.status(201).json(user);
} catch (error) {
res.status(500).json({ message: error.message });
}
};

Setting Up Routes
File: src/routes/userRoutes.ts
import { Router } from 'express';
import { createUser } from '../controllers/userController';

const router: Router = Router();

router.post('/users', createUser);

export default router;

Creating the Express App


File: src/app.ts

import express, { Application } from 'express';


import bodyParser from 'body-parser';
import mongoose from 'mongoose';
import userRoutes from './routes/userRoutes';

const app: Application = express();

app.use(bodyParser.json());

app.use('/api', userRoutes);

const mongoURI: string = 'mongodb://localhost:27017/rest-api';


mongoose.connect(mongoURI, {
useNewUrlParser: true,
useUnifiedTopology: true
}).then(() => {
console.log('Connected to MongoDB');
}).catch(error => {
console.error('Error connecting to MongoDB:', error.message);
});

export default app;

Starting the Server


File: src/server.ts
import app from './app';

const PORT: number = 5000;

app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});

Add a start script to your package.json :

"scripts": {
"start": "ts-node src/server.ts",
"dev": "nodemon src/server.ts"
}

Start the server:

npm run dev

You now have a basic REST API setup with TypeScript and Node.js.

Chapter 12: Real-Time Applications with TypeScript and


Socket.io

Setting Up the Project


Create a new project directory and initialize a Node.js project:

mkdir real-time-app
cd real-time-app
npm init -y

Install the necessary dependencies:

npm install express socket.io


npm install -D typescript @types/node @types/express ts-node nodemon
Create a tsconfig.json file to configure TypeScript:

{
"compilerOptions": {
"target": "ES6",
"module": "commonjs",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true
},
"include": ["src"],
"exclude": ["node_modules"]
}

Setting Up a Real-Time Server


File: src/server.ts
import express from 'express';
import http from 'http';
import { Server, Socket } from 'socket.io';

const app = express();


const server = http.createServer(app);
const io = new Server(server);

io.on('connection', (socket: Socket) => {


console.log('A user connected');

socket.on('message', (message: string) => {


console.log(`Message received: ${message}`);
io.emit('message', message);
});

socket.on('disconnect', () => {
console.log('A user disconnected');
});
});

const PORT: number = 3000;


server.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});

Integrating with a Front-End


Create a simple front-end to test the real-time functionality. In the src directory, create an
index.html file:
<!DOCTYPE html>
<html>
<head>
<title>Real-Time Chat</title>
<script src="/socket.io/socket.io.js"></script>
<script>
document.addEventListener('DOMContentLoaded', () => {
const socket = io();

socket.on('message', (message) => {


const messageList = document.getElementById('messages');
const messageItem = document.createElement('li');
messageItem.textContent = message;
messageList.appendChild(messageItem);
});

document.getElementById('sendButton').addEventListener('click', () => {
const messageInput = document.getElementById('messageInput');
const message = messageInput.value;
socket.emit('message', message);
messageInput.value = '';
});
});
</script>
</head>
<body>
<h1>Real-Time Chat</h1>
<ul id="messages"></ul>
<input id="messageInput" type="text" placeholder="Type a message" />
<button id="sendButton">Send</button>
</body>
</html>

Serve the static file from your Express server: Update src/server.ts

app.use(express.static('src'));

Start the server and open http://localhost:3000 in your browser to see the real-time chat
application in action.

Chapter 13: TypeScript with GraphQL


Setting Up the Project
Create a new project directory and initialize a Node.js project:

mkdir graphql-app
cd graphql-app
npm init -y

Install the necessary dependencies:

npm install express express-graphql graphql


npm install -D typescript @types/node @types/express @types/express-graphql ts-node
nodemon

Create a tsconfig.json file to configure TypeScript:

{
"compilerOptions": {
"target": "ES6",
"module": "commonjs",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true
},
"include": ["src"],
"exclude": ["node_modules"]
}

Setting Up a GraphQL Server


File: src/schema.ts

import { buildSchema } from 'graphql';

export const schema = buildSchema(`


type Query {
hello: String
}
`);
File: src/resolvers.ts

export const root = {


hello: () => {
return 'Hello, world!';
}
};

File: src/server.ts

import express from 'express';


import { graphqlHTTP } from 'express-graphql';
import { schema } from './schema';
import { root } from './resolvers';

const app = express();

app.use('/graphql', graphqlHTTP({
schema: schema,
rootValue: root,
graphiql: true
}));

const PORT: number = 4000;


app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}/graphql`);
});

Start the server:

npm run dev

Open http://localhost:4000/graphql in your browser to interact with the GraphQL API


using GraphiQL.

Chapter 14: Full-Stack Application with TypeScript

Setting Up the Project


Create a new project directory and initialize a Node.js project for the back-end:

mkdir full-stack-app
cd full-stack-app
mkdir server
cd server
npm init -y

Install the necessary dependencies for the back-end:

npm install express mongoose jsonwebtoken bcryptjs

npm install -D typescript @types/node @types/express @types/mongoose


@types/jsonwebtoken @types/bcryptjs ts-node nodemon

Create a tsconfig.json file to configure TypeScript:

{
"compilerOptions": {
"target": "ES6",
"module": "commonjs",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true
},
"include": ["src"],
"exclude": ["node_modules"]
}

Creating the Back-End


File: src/models/user.ts
import mongoose, { Document, Schema } from 'mongoose';

export interface IUser extends Document {


name: string;
email: string;
password: string;
}

const userSchema: Schema = new Schema({


name: { type: String, required: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true }
});

export default mongoose.model<IUser>('User', userSchema);

File: src/controllers/authController.ts
import { Request, Response } from 'express';
import User, { IUser } from '../models/user';
import bcrypt from 'bcryptjs';
import jwt from 'jsonwebtoken';

const SECRET_KEY = 'your_secret_key';

export const register = async (req: Request, res: Response): Promise<void> => {
try {
const { name, email, password } = req.body;
const hashedPassword = await bcrypt.hash(password, 10);
const user: IUser = new User({ name, email, password: hashedPassword });
await user.save();
res.status(201).json({ message: 'User registered successfully' });
} catch (error) {
res.status(500).json({ message: error.message });
}
};

export const login = async (req: Request, res: Response): Promise<void> => {
try {
const { email, password } = req.body;
const user = await User.findOne({ email });
if (!user || !await bcrypt.compare(password, user.password)) {
res.status(401).json({ message: 'Invalid credentials' });
return;
}
const token = jwt.sign({ id: user._id }, SECRET_KEY, { expiresIn: '1h' });
res.status(200).json({ token });
} catch (error) {
res.status(500).json({ message: error.message });
}
};

File: src/routes/authRoutes.ts
import { Router } from 'express';
import { register, login } from '../controllers/authController';

const router: Router = Router();

router.post('/register', register);
router.post('/login', login);

export default router;

File: src/app.ts

import express, { Application } from 'express';


import bodyParser from 'body-parser';
import mongoose from 'mongoose';
import authRoutes from './routes/authRoutes';

const app: Application = express();

app.use(bodyParser.json());

app.use('/api/auth', authRoutes);

const mongoURI: string = 'mongodb://localhost:27017/full-stack-app';


mongoose.connect(mongoURI, {
useNewUrlParser: true,
useUnifiedTopology: true
}).then(() => {
console.log('Connected to MongoDB');
}).catch(error => {
console.error('Error connecting to MongoDB:', error.message);
});

export default app;

File: src/server.ts
import app from './app';

const PORT: number = 5000;

app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});

Add a start script to your package.json :

"scripts": {
"start": "ts-node src/server.ts",
"dev": "nodemon src/server.ts"
}

Start the server:

npm run dev

Creating the Front-End


In the full-stack-app directory, create a new React project with TypeScript using Create React
App:

npx create-react-app client --template typescript


cd client

Install the necessary dependencies for making HTTP requests and managing authentication:

npm install axios react-router-dom


npm install -D @types/react-router-dom

Setting Up Authentication
File: src/App.tsx
import React from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import Register from './components/Register';
import Login from './components/Login';

const App: React.FC = () => {


return (
<Router>
<Switch>
<Route path="/register" component={Register} />
<Route path="/login" component={Login} />
</Switch>
</Router>
);
};

export default App;

File: src/components/Register.tsx
import React, { useState } from 'react';
import axios from 'axios';

const Register: React.FC = () => {


const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');

const handleSubmit = async (event: React.FormEvent) => {


event.preventDefault();
try {
await axios.post('/api/auth/register', { name, email, password });
alert('User registered successfully');
} catch (error) {
alert('Error registering user');
}
};

return (
<form onSubmit={handleSubmit}>
<div>
<label>Name</label>
<input type="text" value={name} onChange={(e) => setName(e.target.value)} />
</div>
<div>
<label>Email</label>
<input type="email" value={email} onChange={(e) => setEmail(e.target.value)}
/>
</div>
<div>
<label>Password</label>
<input type="password" value={password} onChange={(e) =>
setPassword(e.target.value)} />
</div>
<button type="submit">Register</button>
</form>
);
};

export default Register;

File: src/components/Login.tsx
import React, { useState } from 'react';
import axios from 'axios';

const Login: React.FC = () => {


const [email, setEmail] = useState('');
const [password, setPassword] = useState('');

const handleSubmit = async (event: React.FormEvent) => {


event.preventDefault();
try {
const response = await axios.post('/api/auth/login', { email, password });
localStorage.setItem('token', response.data.token);
alert('User logged in successfully');
} catch (error) {
alert('Error logging in');
}
};

return (
<form onSubmit={handleSubmit}>
<div>
<label>Email</label>
<input type="email" value={email} onChange={(e) => setEmail(e.target.value)}
/>
</div>
<div>
<label>Password</label>
<input type="password" value={password} onChange={(e) =>
setPassword(e.target.value)} />
</div>
<button type="submit">Login</button>
</form>
);
};

export default Login;

Running the Full-Stack Application


In the full-stack-app/client directory, update the package.json file to include a proxy for
the API:

"proxy": "http://localhost:5000"
Start the React development server:

npm start

Now you have a full-stack application with a TypeScript back-end and front-end, including user
registration and login functionality.

You might also like