![]() |
🧩 Obiettivo
Imparare a strutturare un'applicazione realistica con TypeScript, integrando:
moduli
interfacce e tipi
gestione degli errori
accesso a dati (es. da un’API)
organizzazione del progetto
📁 Struttura del progetto
Un buon punto di partenza potrebbe essere un'app che gestisce utenti.
Struttura base del progetto:
users-app/
├── src/
│ ├── models/
│ │ └── User.ts
│ ├── services/
│ │ └── UserService.ts
│ ├── utils/
│ │ └── logger.ts
│ └── index.ts
├── tsconfig.json
├── package.json
👤 1. Definizione del modello User
src/models/User.ts:
export interface User {
id: number;
name: string;
email: string;
isActive: boolean;
}
👉 Questo ci permette di garantire che ovunque usiamo un User, rispetti sempre questa struttura.
🛠️ 2. Creazione di un servizio
src/services/UserService.ts:
import { User } from "../models/User";
export class UserService {
private users: User[] = [];
add(user: User): void {
this.users.push(user);
}
findByEmail(email: string): User | undefined {
return this.users.find(u => u.email === email);
}
getActiveUsers(): User[] {
return this.users.filter(u => u.isActive);
}
}
Note:
-
User | undefined: la funzione può non trovare nulla -
Tutto è tipizzato, chiaro e verificabile
🧰 3. Utilità e logging
src/utils/logger.ts:
export function logInfo(msg: string): void {
console.log("[INFO]", msg);
}
export function logErrore(msg: string): void {
console.error("[ERRORE]", msg);
}
🚀 4. Entry point: index.ts
src/index.ts:
import { UserService } from "./services/UserService";
import { logInfo, logErrore } from "./utils/logger";
const userService = new UserService();
userService.add({
id: 1,
name: "Elisa",
email: "elisa@example.com",
isActive: true,
});
const user = userService.findByEmail("elisa@example.com");
if (user) {
logInfo(`User found: ${user.name}`);
} else {
logErrore("User not found");
}
👉 Questo è già un mini backend (o parte di una logica di business) interamente scritto in TypeScript, leggibile, scalabile e sicuro.
🛑 5. Gestione degli errori e tipi personalizzati
TypeScript permette anche di tipizzare gli errori, o creare wrapper più solidi per situazioni comuni:
type Risultato<T> =
| { ok: true; value: T }
| { ok: false; error: string };
function findUser(email: string): Result<User> {
const u = userService.findByEmail(email);
if (u) {
return { ok: true, value: u };
} else {
return { ok: false, error: "No user found" };
}
}
🧪 6. Esempio: chiamata fetch + async/await + tipi
Simuliamo una fetch a un’API REST (tipo JSONPlaceholder).
interface Todo {
id: number;
title: string;
completed: boolean;
}
async function getTodos(): Promise<Todo[]> {
const res = await fetch("https://jsonplaceholder.typicode.com/todos");
if (!res.ok) throw new Error("Error retrieving data");
return await res.json();
}
Tipi chiari, struttura solida, gestione degli errori: tutto in pieno stile TypeScript.
🔁 7. Integrazione con moduli JS esistenti
Puoi usare librerie JavaScript esistenti tipizzandole:
npm install axios
npm install --save-dev @types/axios
Poi usarla come se fosse nativa TypeScript:
import axios from "axios";
async function getUsers(): Promise<User[]> {
const res = await axios.get<User[]>("https://api.miosito.it/users");
return res.data;
}
🔒 8. Vantaggi reali in un progetto
✅ Riduci drasticamente i bug da “undefined”
✅ Autocompletamento intelligente in tutta la codebase
✅ Codice più leggibile, mantenibile, documentato
✅ Riduci i test banali: i tipi fanno già tanta validazione
✅ Più facile fare refactoring in sicurezza
📌 In sintesi
Costruire un progetto reale in TypeScript ti permette di:
-
Definire contratti chiari e riutilizzabili
-
Evitare errori comuni
-
Scrivere codice più scalabile
-
Collaborare meglio con team (o… con te stesso tra 3 mesi 😄)
Follow me #techelopment
Official site: www.techelopment.it
facebook: Techelopment
instagram: @techelopment
X: techelopment
Bluesky: @techelopment
telegram: @techelopment_channel
whatsapp: Techelopment
youtube: @techelopment
