TypeScript strict mode: non si torna indietro
Come abbiamo migrato un codebase di 50k righe a strict mode e perché ogni nuovo progetto parte da lì.
lintedhub
redazione tecnicaTypeScript strict mode: non si torna indietro
"Strict mode è troppo restrittivo." L'abbiamo sentito. L'abbiamo pure pensato. Poi abbiamo fatto la migrazione e non torneremmo mai indietro.
Cosa include strict mode
Prima di tutto, chiariamo cosa significa "strict": true:
{
"compilerOptions": {
"strict": true
// Equivale a:
// "noImplicitAny": true,
// "noImplicitThis": true,
// "alwaysStrict": true,
// "strictBindCallApply": true,
// "strictNullChecks": true,
// "strictFunctionTypes": true,
// "strictPropertyInitialization": true,
// "useUnknownInCatchVariables": true
}
}
La flag più importante? strictNullChecks. Da sola vale la migrazione.
Il problema con nullable types
Senza strict mode:
function getUser(id: string) {
return users.find(u => u.id === id);
}
const user = getUser("123");
console.log(user.name); // Runtime: Cannot read property 'name' of undefined
TypeScript non si lamenta. Il bug esplode in produzione.
Con strict mode:
function getUser(id: string) {
return users.find(u => u.id === id);
}
const user = getUser("123");
console.log(user.name); // Error: 'user' is possibly 'undefined'
Il compilatore ti forza a gestire il caso:
const user = getUser("123");
if (user) {
console.log(user.name); // OK
}
// O con optional chaining
console.log(user?.name);
// O con assertion (quando sei sicuro)
console.log(user!.name); // Usare con cautela
La strategia di migrazione
Abbiamo migrato 50k righe di codice in 3 settimane. Ecco come.
Fase 1: Preparazione
{
"compilerOptions": {
"strict": false,
"noImplicitAny": true // Inizia da qui
}
}
noImplicitAny da solo trova tonnellate di problemi. Sistemali prima.
Fase 2: Null checks incrementali
{
"compilerOptions": {
"noImplicitAny": true,
"strictNullChecks": true // Il big one
}
}
Aspettati molti errori. È normale. Procedi file per file.
Fase 3: Il resto
{
"compilerOptions": {
"strict": true // Full send
}
}
A questo punto, gli errori rimanenti sono pochi.
Pattern utili post-migrazione
Type guards
function isUser(obj: unknown): obj is User {
return (
typeof obj === "object" &&
obj !== null &&
"id" in obj &&
"name" in obj
);
}
const data = await fetchSomething();
if (isUser(data)) {
console.log(data.name); // TypeScript sa che è User
}
Assertion functions
function assertUser(obj: unknown): asserts obj is User {
if (!isUser(obj)) {
throw new Error("Invalid user object");
}
}
const data = await fetchSomething();
assertUser(data);
console.log(data.name); // OK dopo l'assertion
NonNullable utility type
type MaybeUser = User | null | undefined;
type DefinitelyUser = NonNullable<MaybeUser>; // User
I numeri
Dopo la migrazione:
- Bug in produzione: -60% (sì, davvero)
- Tempo di code review: -20% (meno da controllare)
- Onboarding: più veloce (il codice è auto-documentante)
Conclusione
Strict mode non è "troppo restrittivo". È esattamente restrittivo quanto serve per catturare bug prima che raggiungano gli utenti.
Ogni nuovo progetto dovrebbe partire con "strict": true. Per progetti esistenti, la migrazione richiede sforzo ma ripaga rapidamente.
Il type system è il tuo alleato. Lascialo fare il suo lavoro.
Hai un progetto in mente?
Trasformiamo scelte tecniche complesse in sistemi in produzione.
Se stai valutando stack, architetture o integrazioni AI, parliamone. Niente pitch: una conversazione tecnica.
ParliamoneContinua a leggere
Tutti gli articoliVibe coding con architettura: il workflow che usiamo davvero
Vibe coding non è una parolaccia se hai esperienza sul campo. Ecco come l'AI scrive il codice e a noi resta il tempo per architettura, performance, sicurezza, validazione.
Eval set: il test driven development per i sistemi AI
Senza un eval set scritto, ogni modifica a un prompt è una preghiera. Ecco come costruiamo eval realistici, li mettiamo in CI e perché trattiamo i prompt come codice di produzione.
Direttive scritte: trattare i prompt come codice di produzione
Un prompt non è un messaggio in chat, è un artefatto di sistema. Come strutturiamo direttive, le versioniamo, le rivediamo in PR e perché evitiamo le "chat improvvisate" sui task seri.