DEV Community

frontendfacile.it
frontendfacile.it

Posted on • Originally published at frontendfacile.it

Express con TypeScript: setup pulito, typing concreto e workflow senza attriti

Dalla configurazione del progetto al primo endpoint tipizzato, con build e start script pronti per crescere.

TypeScript e Express stanno bene insieme per un motivo semplice: Express ti fa andare veloce, TypeScript ti evita di pagare quella velocità in bug stupidi e refactor dolorosi. Se l’obiettivo è costruire API manutenibili (anche piccole), vale la pena impostare da subito una base pulita.

Qui sotto trovi un percorso pratico: setup del progetto, tsconfig, primo server, compilazione e un workflow tramite script npm. Il risultato è una mini-API pronta a crescere in rotte, controller e middleware tipizzati.


1) Dipendenze: Express “runtime”, TypeScript “dev-time”

Parti come un normale progetto Node:

npm init -y
Enter fullscreen mode Exit fullscreen mode

Installa Express come dipendenza runtime:

npm install express
Enter fullscreen mode Exit fullscreen mode

Poi aggiungi TypeScript e i tipi di Express come devDependencies (Express è JavaScript puro: senza @types TypeScript non conosce Request, Response, ecc.):

npm install -D typescript @types/express
Enter fullscreen mode Exit fullscreen mode

Un tsconfig sensato senza reinventare la ruota

Scrivere un tsconfig.json “perfetto” a mano è una perdita di tempo. Molto meglio estendere una base già collaudata per la tua versione di Node.

Ad esempio, per Node 20:

npm install -D @tsconfig/node20
Enter fullscreen mode Exit fullscreen mode

Crea tsconfig.json e imposta estensione + due directory chiave:

{
  "extends": "@tsconfig/node20/tsconfig.json",
  "compilerOptions": {
    "rootDir": "source",
    "outDir": "dist"
  }
}
Enter fullscreen mode Exit fullscreen mode
  • rootDir: dove vivi con i file TypeScript (qui: source/).
  • outDir: dove finiscono i JavaScript compilati (qui: dist/).

Questo pattern è semplice ma importantissimo: separa sorgente e build output, evitando confusione e import strani.


2) Struttura minima del progetto

Crea la cartella e l’entry point:

source/
  index.ts
tsconfig.json
package.json
Enter fullscreen mode Exit fullscreen mode

Dentro source/index.ts, lo scheletro base di Express:

import express from "express";

const app = express();
const port = 8000;

app.listen(port, () => {
  console.log(`listening on port ${port}`);
});
Enter fullscreen mode Exit fullscreen mode

Un pizzico di typing (senza forzature)

Molto è già inferito da TypeScript, ma esercitarsi a pensare per tipi aiuta. Puoi tipizzare esplicitamente l’app e il return type della callback:

import express, { type Express } from "express";

const app: Express = express();
const port = 8000;

app.listen(port, (): void => {
  console.log(`listening on port ${port}`);
});
Enter fullscreen mode Exit fullscreen mode

Non è obbligatorio. È allenamento: quando arriverai a tipizzare middleware, handler, query param e payload, questa disciplina torna utilissima.


3) Compilare e avviare: Node non esegue TypeScript

Node non capisce .ts nativamente: devi compilare.

Compila con il compiler TypeScript:

npx tsc
Enter fullscreen mode Exit fullscreen mode

Otterrai il build in dist/ (ad esempio dist/index.js). Poi avvii:

node dist/index.js
Enter fullscreen mode Exit fullscreen mode

A questo punto il server gira, ma se non hai rotte otterrai un classico 404 su /.


4) Prima rotta: risposta JSON

Aggiungi una rotta GET / che risponde con un JSON (anche vuoto, giusto per testare la pipeline):

app.get("/", (req, res) => {
  res.json({});
});
Enter fullscreen mode Exit fullscreen mode

Poi:

npx tsc
node dist/index.js
Enter fullscreen mode Exit fullscreen mode

5) Modellare dati reali: tipizzare un “pet” (o qualsiasi dominio)

Restituire {} serve solo per verificare che tutto funzioni. Il passo successivo è introdurre un piccolo modello dati e tipizzarlo.

Esempio con un tipo Pet:

type Pet = {
  name: string;
  species: string;
  adopted: boolean;
  age: number;
};

const pets: Pet[] = [
  { name: "Rubik", species: "cat", adopted: true, age: 3 },
  { name: "Pickle", species: "dog", adopted: false, age: 5 }
];

app.get("/", (req, res) => {
  res.json(pets);
});
Enter fullscreen mode Exit fullscreen mode

Qui TypeScript ti protegge da:

  • proprietà mancanti o con tipo sbagliato (age: "3" → errore),
  • dati incoerenti tra i vari oggetti,
  • refactor fragili quando cambi il modello.

6) Workflow migliore: script npm per build + run

Digitare ogni volta npx tsc e poi node dist/index.js diventa rapidamente noioso. Gli script npm sistemano la routine e la rendono standard.

In package.json:

{
  "scripts": {
    "build": "npx tsc",
    "start": "npx tsc && node dist/index.js"
  }
}
Enter fullscreen mode Exit fullscreen mode

Ora puoi fare:

npm run start
Enter fullscreen mode Exit fullscreen mode
  • prima compila
  • poi avvia l’output compilato

È una base semplice, ma già “production-shaped”: separa compilation e runtime, ed evita di eseguire TypeScript direttamente in ambienti dove non vuoi dipendenze extra.


Sintesi e implicazione pratica

Un setup Express + TypeScript ben fatto non richiede un framework aggiuntivo: bastano dipendenze corrette, un tsconfig sensato e una convenzione chiara (source/dist/). Da lì, ogni miglioramento (rotte tipizzate, controller, middleware, validazione input, gestione errori) poggia su fondamenta solide.

Se oggi stai iniziando un’API Express, il consiglio pratico è: imposta subito rootDir/outDir, aggiungi @types/express, crea gli script build/start e inizia a modellare il dominio con tipi espliciti. Il tempo risparmiato in debug e refactor ripaga molto più di quanto costi la configurazione iniziale.


Articolo originale: https://frontendfacile.it/blog/express-con-typescript-setup-pulito-typing-concreto-e-workflow-senza-attriti

Top comments (0)