JavaScript/TypeScript
JavaScript and TypeScript are essential languages for modern web development and data visualization. JavaScript provides dynamic web functionality, while TypeScript adds static typing for large-scale applications.
JavaScript Fundamentals
Language Features
- Dynamic typing: Flexible variable types
- First-class functions: Functions as values
- Prototype-based: Object-oriented programming
- Event-driven: Asynchronous programming model
- Interpreted: Runtime execution
Modern JavaScript (ES6+)
// Arrow functions and destructuring
const processData = (data) => {
const { name, value, category } = data;
return {
processedName: name.toUpperCase(),
normalizedValue: value / 100,
category
};
};
// Template literals and async/await
const fetchData = async (url) => {
try {
const response = await fetch(url);
const data = await response.json();
return data.map(processData);
} catch (error) {
console.error(`Failed to fetch data: {error.message}`);
}
};
TypeScript Advantages
Type Safety
interface DataPoint {
id: number;
timestamp: Date;
value: number;
category: string;
}
type ProcessedData = {
[key: string]: {
count: number;
average: number;
total: number;
};
};
function aggregateData(data: DataPoint[]): ProcessedData {
const result: ProcessedData = {};
data.forEach(point => {
if (!result[point.category]) {
result[point.category] = { count: 0, average: 0, total: 0 };
}
result[point.category].count += 1;
result[point.category].total += point.value;
});
// Calculate averages
Object.keys(result).forEach(category => {
result[category].average = result[category].total / result[category].count;
});
return result;
}
Advanced Types
// Generic types for reusability
interface ApiResponse<T> {
data: T;
status: number;
message: string;
}
// Union types for flexibility
type ChartType = 'bar' | 'line' | 'scatter' | 'pie';
// Utility types for transformations
type PartialUser = Partial<User>;
type RequiredFields = Required<Pick<User, 'id' | 'email'>>;
Frontend Development
React/Next.js
import React, { useState, useEffect } from 'react';
import { NextPage } from 'next';
interface DashboardProps {
initialData: DataPoint[];
}
const Dashboard: NextPage<DashboardProps> = ({ initialData }) => {
const [data, setData] = useState<DataPoint[]>(initialData);
const [filter, setFilter] = useState<string>('');
const [isLoading, setIsLoading] = useState<boolean>(false);
useEffect(() => {
const fetchLatestData = async () => {
setIsLoading(true);
try {
const response = await fetch('/api/data');
const newData: DataPoint[] = await response.json();
setData(newData);
} catch (error) {
console.error('Failed to fetch data:', error);
} finally {
setIsLoading(false);
}
};
const interval = setInterval(fetchLatestData, 30000); // Update every 30s
return () => clearInterval(interval);
}, []);
const filteredData = data.filter(item =>
item.category.toLowerCase().includes(filter.toLowerCase())
);
return (
<div className="dashboard">
<input
type="text"
placeholder="Filter by category..."
value={filter}
onChange={(e) => setFilter(e.target.value)}
/>
{isLoading ? (
<div>Loading...</div>
) : (
<DataVisualization data={filteredData} />
)}
</div>
);
};
Data Visualization
D3.js
import * as d3 from 'd3';
function createScatterPlot(data, containerSelector) {
const margin = { top: 20, right: 30, bottom: 40, left: 40 };
const width = 800 - margin.left - margin.right;
const height = 600 - margin.top - margin.bottom;
// Create SVG
const svg = d3.select(containerSelector)
.append('svg')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom);
const g = svg.append('g')
.attr('transform', `translate([mathematical expression]{margin.top})`);
// Scales
const xScale = d3.scaleLinear()
.domain(d3.extent(data, d => d.x))
.range([0, width]);
const yScale = d3.scaleLinear()
.domain(d3.extent(data, d => d.y))
.range([height, 0]);
// Add dots
g.selectAll('circle')
.data(data)
.enter().append('circle')
.attr('cx', d => xScale(d.x))
.attr('cy', d => yScale(d.y))
.attr('r', 4)
.attr('fill', d => d.category === 'A' ? 'steelblue' : 'orange');
// Add axes
g.append('g')
.attr('transform', `translate(0,{height})`)
.call(d3.axisBottom(xScale));
g.append('g')
.call(d3.axisLeft(yScale));
}
Chart.js
import Chart from 'chart.js/auto';
function createTimeSeriesChart(canvasId, timeSeriesData) {
const ctx = document.getElementById(canvasId).getContext('2d');
return new Chart(ctx, {
type: 'line',
data: {
labels: timeSeriesData.map(d => d.date),
datasets: [{
label: 'Daily Values',
data: timeSeriesData.map(d => d.value),
borderColor: 'rgb(75, 192, 192)',
backgroundColor: 'rgba(75, 192, 192, 0.2)',
tension: 0.4
}]
},
options: {
responsive: true,
scales: {
x: {
type: 'time',
time: {
unit: 'day'
}
},
y: {
beginAtZero: true
}
},
plugins: {
tooltip: {
callbacks: {
title: function(context) {
return new Date(context[0].label).toLocaleDateString();
}
}
}
}
}
});
}
API Integration
RESTful APIs
class DataService {
private baseUrl: string;
constructor(baseUrl: string) {
this.baseUrl = baseUrl;
}
async fetchData<T>(endpoint: string): Promise<T> {
const response = await fetch(`[mathematical expression]{endpoint}`);
if (!response.ok) {
throw new Error(`HTTP error! status: {response.status}`);
}
return await response.json();
}
async postData<T>(endpoint: string, data: any): Promise<T> {
const response = await fetch(`[mathematical expression]{endpoint}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data)
});
return await response.json();
}
}
// Usage
const dataService = new DataService('/api');
const userData = await dataService.fetchData<User[]>('/users');
WebSocket for Real-time Data
class RealTimeDataConnection {
private ws: WebSocket | null = null;
private listeners: Map<string, Function[]> = new Map();
connect(url: string): void {
this.ws = new WebSocket(url);
this.ws.onopen = () => {
console.log('WebSocket connected');
};
this.ws.onmessage = (event) => {
const data = JSON.parse(event.data);
this.emit(data.type, data.payload);
};
this.ws.onclose = () => {
console.log('WebSocket disconnected');
// Implement reconnection logic
setTimeout(() => this.connect(url), 5000);
};
}
on(event: string, callback: Function): void {
if (!this.listeners.has(event)) {
this.listeners.set(event, []);
}
this.listeners.get(event)!.push(callback);
}
private emit(event: string, data: any): void {
const callbacks = this.listeners.get(event) || [];
callbacks.forEach(callback => callback(data));
}
send(data: any): void {
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
this.ws.send(JSON.stringify(data));
}
}
}
Node.js Backend
Express.js API
import express from 'express';
import cors from 'cors';
import { body, validationResult } from 'express-validator';
const app = express();
app.use(cors());
app.use(express.json());
// Data validation middleware
const validateData = [
body('name').isString().isLength({ min: 1 }),
body('value').isNumeric(),
body('category').isString().isIn(['A', 'B', 'C'])
];
app.post('/api/data', validateData, async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
try {
const { name, value, category } = req.body;
const result = await saveData({ name, value, category });
res.json({ success: true, data: result });
} catch (error) {
console.error('Error saving data:', error);
res.status(500).json({ error: 'Internal server error' });
}
});
app.get('/api/data/:category', async (req, res) => {
try {
const { category } = req.params;
const data = await fetchDataByCategory(category);
res.json(data);
} catch (error) {
console.error('Error fetching data:', error);
res.status(500).json({ error: 'Internal server error' });
}
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server running on port {PORT}`);
});
Popular Libraries & Frameworks
Frontend
- React: Component-based UI library
- Next.js: Full-stack React framework
- Vue.js: Progressive JavaScript framework
- Angular: Full-featured application platform
Data Visualization
- D3.js: Data-driven document manipulation
- Chart.js: Simple yet flexible charting
- Plotly.js: Interactive scientific charts
- Observable Plot: Grammar of graphics
Backend
- Express.js: Minimal web framework
- Fastify: Fast web framework
- NestJS: Scalable Node.js framework
- Koa.js: Next-generation web framework
Development Tools
- Webpack: Module bundler
- Vite: Fast build tool
- ESLint: Code linting
- Prettier: Code formatting
- Jest: Testing framework
Best Practices
Code Quality
- Type safety: Use TypeScript for large projects
- Code splitting: Bundle optimization
- Error handling: Proper error boundaries
- Performance: Optimize rendering and network requests
Security
- Input validation: Sanitize user inputs
- CORS: Proper cross-origin configuration
- Authentication: Secure token handling
- HTTPS: Encrypted communication
Testing
// Unit testing with Jest
describe('DataProcessor', () => {
test('should aggregate data correctly', () => {
const input = [
{ category: 'A', value: 10 },
{ category: 'A', value: 20 },
{ category: 'B', value: 15 }
];
const result = aggregateData(input);
expect(result.A.count).toBe(2);
expect(result.A.average).toBe(15);
expect(result.B.count).toBe(1);
});
});
When to Choose JavaScript/TypeScript
Ideal For
- Interactive web applications
- Data visualization dashboards
- Real-time applications
- API development
- Cross-platform mobile apps (React Native)
- Desktop applications (Electron)
Consider Alternatives When
- CPU-intensive computations
- System programming
- High-performance computing
- Memory-constrained environments
JavaScript/TypeScript provides excellent tools for creating interactive, data-driven web applications with rich visualization capabilities, making them essential for modern data presentation and user interfaces.