JavaScript TypeScript Integration
Master TypeScript integration, type systems, and how to leverage TypeScript for building robust JavaScript applications
45 min•By Priygop Team•Last updated: Feb 2026
TypeScript Basics
TypeScript is a superset of JavaScript that adds static typing, interfaces, and advanced language features. It helps catch errors early, provides better tooling support, and makes JavaScript code more maintainable.
TypeScript Configuration
Example
// tsconfig.json
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"lib": ["DOM", "DOM.Iterable", "ESNext"],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": ["src"],
"exclude": ["node_modules"]
}
// Basic TypeScript types
let name: string = 'John Doe';
let age: number = 30;
let isActive: boolean = true;
let hobbies: string[] = ['reading', 'coding'];
let user: { name: string; age: number } = { name: 'John', age: 30 };
// Union types
let status: 'loading' | 'success' | 'error' = 'loading';
let id: string | number = 'abc123';
// Type aliases
type User = {
id: number;
name: string;
email: string;
isActive: boolean;
};
type UserStatus = 'active' | 'inactive' | 'pending';
// Interfaces
interface Product {
id: number;
name: string;
price: number;
category: string;
inStock: boolean;
}
interface ProductWithDiscount extends Product {
discount: number;
discountedPrice: number;
}
// Function types
type MathFunction = (a: number, b: number) => number;
type CallbackFunction = (data: any) => void;
const add: MathFunction = (a, b) => a + b;
const multiply: MathFunction = (a, b) => a * b;
// Generic types
function identity<T>(arg: T): T {
return arg;
}
function createArray<T>(length: number, value: T): T[] {
return Array(length).fill(value);
}
// Usage
const stringArray = createArray(3, 'hello');
const numberArray = createArray(5, 0);TypeScript with React
Example
// React component with TypeScript
import React, { useState, useEffect } from 'react';
interface User {
id: number;
name: string;
email: string;
avatar?: string;
}
interface UserCardProps {
user: User;
onEdit: (user: User) => void;
onDelete: (id: number) => void;
isAdmin?: boolean;
}
const UserCard: React.FC<UserCardProps> = ({
user,
onEdit,
onDelete,
isAdmin = false
}) => {
const [isEditing, setIsEditing] = useState<boolean>(false);
const [editedUser, setEditedUser] = useState<User>(user);
const handleSave = () => {
onEdit(editedUser);
setIsEditing(false);
};
const handleCancel = () => {
setEditedUser(user);
setIsEditing(false);
};
return (
<div className="user-card">
{isEditing ? (
<div className="edit-form">
<input
type="text"
value={editedUser.name}
onChange={(e) => setEditedUser({
...editedUser,
name: e.target.value
})}
/>
<input
type="email"
value={editedUser.email}
onChange={(e) => setEditedUser({
...editedUser,
email: e.target.value
})}
/>
<button onClick={handleSave}>Save</button>
<button onClick={handleCancel}>Cancel</button>
</div>
) : (
<div className="user-info">
<h3>{user.name}</h3>
<p>{user.email}</p>
{user.avatar && (
<img src={user.avatar} alt={user.name} />
)}
<div className="actions">
<button onClick={() => setIsEditing(true)}>Edit</button>
{isAdmin && (
<button onClick={() => onDelete(user.id)}>Delete</button>
)}
</div>
</div>
)}
</div>
);
};
// Custom hooks with TypeScript
interface UseCounterReturn {
count: number;
increment: () => void;
decrement: () => void;
reset: () => void;
setCount: (value: number) => void;
}
const useCounter = (initialValue: number = 0): UseCounterReturn => {
const [count, setCount] = useState<number>(initialValue);
const increment = () => setCount(prev => prev + 1);
const decrement = () => setCount(prev => prev - 1);
const reset = () => setCount(initialValue);
return {
count,
increment,
decrement,
reset,
setCount
};
};
// API service with TypeScript
interface ApiResponse<T> {
data: T;
status: number;
message: string;
}
interface UserService {
getUsers(): Promise<ApiResponse<User[]>>;
getUser(id: number): Promise<ApiResponse<User>>;
createUser(user: Omit<User, 'id'>): Promise<ApiResponse<User>>;
updateUser(id: number, user: Partial<User>): Promise<ApiResponse<User>>;
deleteUser(id: number): Promise<ApiResponse<void>>;
}
class UserApiService implements UserService {
private baseUrl: string = 'https://api.example.com/users';
async getUsers(): Promise<ApiResponse<User[]>> {
const response = await fetch(this.baseUrl);
const data = await response.json();
return {
data,
status: response.status,
message: 'Users retrieved successfully'
};
}
async getUser(id: number): Promise<ApiResponse<User>> {
const response = await fetch(`${this.baseUrl}/${id}`);
const data = await response.json();
return {
data,
status: response.status,
message: 'User retrieved successfully'
};
}
async createUser(user: Omit<User, 'id'>): Promise<ApiResponse<User>> {
const response = await fetch(this.baseUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(user)
});
const data = await response.json();
return {
data,
status: response.status,
message: 'User created successfully'
};
}
async updateUser(id: number, user: Partial<User>): Promise<ApiResponse<User>> {
const response = await fetch(`${this.baseUrl}/${id}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(user)
});
const data = await response.json();
return {
data,
status: response.status,
message: 'User updated successfully'
};
}
async deleteUser(id: number): Promise<ApiResponse<void>> {
const response = await fetch(`${this.baseUrl}/${id}`, {
method: 'DELETE'
});
return {
data: undefined,
status: response.status,
message: 'User deleted successfully'
};
}
}Practice Exercise: TypeScript
Example
// Exercise: Build a TypeScript Todo Application
// 1. Define types and interfaces
interface Todo {
id: number;
title: string;
description?: string;
completed: boolean;
priority: 'low' | 'medium' | 'high';
createdAt: Date;
updatedAt: Date;
}
interface TodoFilters {
completed?: boolean;
priority?: Todo['priority'];
search?: string;
}
interface TodoStats {
total: number;
completed: number;
pending: number;
byPriority: Record<Todo['priority'], number>;
}
// 2. Create Todo service
class TodoService {
private todos: Todo[] = [];
private nextId: number = 1;
addTodo(todoData: Omit<Todo, 'id' | 'completed' | 'createdAt' | 'updatedAt'>): Todo {
const todo: Todo = {
...todoData,
id: this.nextId++,
completed: false,
createdAt: new Date(),
updatedAt: new Date()
};
this.todos.push(todo);
return todo;
}
getTodos(filters?: TodoFilters): Todo[] {
let filteredTodos = [...this.todos];
if (filters?.completed !== undefined) {
filteredTodos = filteredTodos.filter(todo => todo.completed === filters.completed);
}
if (filters?.priority) {
filteredTodos = filteredTodos.filter(todo => todo.priority === filters.priority);
}
if (filters?.search) {
const searchLower = filters.search.toLowerCase();
filteredTodos = filteredTodos.filter(todo =>
todo.title.toLowerCase().includes(searchLower) ||
todo.description?.toLowerCase().includes(searchLower)
);
}
return filteredTodos;
}
getTodo(id: number): Todo | undefined {
return this.todos.find(todo => todo.id === id);
}
updateTodo(id: number, updates: Partial<Omit<Todo, 'id' | 'createdAt'>>): Todo | undefined {
const todoIndex = this.todos.findIndex(todo => todo.id === id);
if (todoIndex === -1) return undefined;
this.todos[todoIndex] = {
...this.todos[todoIndex],
...updates,
updatedAt: new Date()
};
return this.todos[todoIndex];
}
deleteTodo(id: number): boolean {
const initialLength = this.todos.length;
this.todos = this.todos.filter(todo => todo.id !== id);
return this.todos.length < initialLength;
}
toggleTodo(id: number): Todo | undefined {
const todo = this.getTodo(id);
if (!todo) return undefined;
return this.updateTodo(id, { completed: !todo.completed });
}
getStats(): TodoStats {
const total = this.todos.length;
const completed = this.todos.filter(todo => todo.completed).length;
const pending = total - completed;
const byPriority = {
low: this.todos.filter(todo => todo.priority === 'low').length,
medium: this.todos.filter(todo => todo.priority === 'medium').length,
high: this.todos.filter(todo => todo.priority === 'high').length
};
return { total, completed, pending, byPriority };
}
}
// 3. Create React components with TypeScript
import React, { useState, useEffect } from 'react';
interface TodoAppProps {
service: TodoService;
}
const TodoApp: React.FC<TodoAppProps> = ({ service }) => {
const [todos, setTodos] = useState<Todo[]>([]);
const [filters, setFilters] = useState<TodoFilters>({});
const [stats, setStats] = useState<TodoStats>({
total: 0,
completed: 0,
pending: 0,
byPriority: { low: 0, medium: 0, high: 0 }
});
useEffect(() => {
updateTodos();
updateStats();
}, [filters]);
const updateTodos = () => {
setTodos(service.getTodos(filters));
};
const updateStats = () => {
setStats(service.getStats());
};
const handleAddTodo = (todoData: Omit<Todo, 'id' | 'completed' | 'createdAt' | 'updatedAt'>) => {
service.addTodo(todoData);
updateTodos();
updateStats();
};
const handleToggleTodo = (id: number) => {
service.toggleTodo(id);
updateTodos();
updateStats();
};
const handleDeleteTodo = (id: number) => {
service.deleteTodo(id);
updateTodos();
updateStats();
};
return (
<div className="todo-app">
<TodoForm onAdd={handleAddTodo} />
<TodoFilters filters={filters} onFiltersChange={setFilters} />
<TodoList
todos={todos}
onToggle={handleToggleTodo}
onDelete={handleDeleteTodo}
/>
<TodoStats stats={stats} />
</div>
);
};
// 4. Test the application
const todoService = new TodoService();
// Add some todos
todoService.addTodo({
title: 'Learn TypeScript',
description: 'Master TypeScript fundamentals',
priority: 'high'
});
todoService.addTodo({
title: 'Build React app',
description: 'Create a todo application',
priority: 'medium'
});
todoService.addTodo({
title: 'Write tests',
description: 'Add unit and integration tests',
priority: 'low'
});
// Get todos with filters
const highPriorityTodos = todoService.getTodos({ priority: 'high' });
const completedTodos = todoService.getTodos({ completed: true });
// Get statistics
const stats = todoService.getStats();
console.log('Todo Statistics:', stats);