BaliseTonSite

Prevenir les bugs

Les enchantements defensifs : TypeScript, linting, tests.

8.1Bouclier 1 : TypeScript (le compilateur te protege)

TypeScript attrape une ENORME categorie de bugs avant meme que tu executes ton code. C'est comme avoir un scanner qui detecte les pieges avant que tu marches dessus.

Bugs que TypeScript attrape automatiquementtypescript
// Sans TypeScript : bug silencieux en production
function greet(user) {
  return "Hello " + user.name  // Si user est null -> crash en prod !
}

// Avec TypeScript : erreur a l'ecriture
function greet(user: User | null) {
  return "Hello " + user.name
  //                 ^^^^ Object is possibly 'null'
  // TypeScript te FORCE a gerer le cas null
}

// Le fix que TypeScript te suggere :
function greet(user: User | null) {
  if (!user) return "Hello visiteur"
  return "Hello " + user.name  // OK, user est forcement User ici
}

// Activer le mode strict dans tsconfig.json
// "strict": true  <- attrape 10x plus de bugs

8.2Bouclier 2 : ESLint (l'inspecteur de code)

ESLint detecte les patterns problematiques dans ton code. Il ne verifie pas les types (ca c'est TypeScript), mais les mauvaises habitudes.

Regles ESLint qui sauvent des viestypescript
// eslint-disable-next-line @typescript-eslint/no-unused-vars
// -> detecte les imports et variables non utilises

// eslint: react-hooks/exhaustive-deps
// -> detecte les dependances manquantes dans useEffect
useEffect(() => {
  fetchUser(userId) // ESLint : userId manque dans les deps
}, []) // Warning !

// eslint: react-hooks/rules-of-hooks
// -> detecte les hooks appeles conditionnellement
if (loggedIn) {
  const [user, setUser] = useState() // ERREUR : hook conditionnel
}

// eslint: no-console
// -> supprime les console.log oublies avant la prod

8.3Bouclier 3 : Le pattern "guard clause"

Au lieu de faire des if/else imbriques, traite les cas d'erreur En premier. C'est un enchantement simple mais redoutablement efficace.

Guard clauses : traiter les erreurs en premiertypescript
// AVANT : if/else imbrique = jungle
async function getUser(userId: string) {
  if (userId) {
    const response = await fetch(`/api/users/${userId}`)
    if (response.ok) {
      const data = await response.json()
      if (data) {
        return data
      } else {
        throw new Error("No data")
      }
    } else {
      throw new Error("Fetch failed")
    }
  } else {
    throw new Error("No userId")
  }
}

// APRES : guard clauses = clair et lineaire
async function getUser(userId: string) {
  if (!userId) throw new Error("No userId")

  const response = await fetch(`/api/users/${userId}`)
  if (!response.ok) throw new Error(`Fetch failed: ${response.status}`)

  const data = await response.json()
  if (!data) throw new Error("No data")

  return data
}

8.4Bouclier 4 : Les valeurs par defaut

Valeurs par defaut : jamais de undefined surprisetypescript
// Props avec default
interface CardProps {
  title: string
  variant?: 'primary' | 'secondary'
  items?: string[]
}

function Card({ title, variant = 'primary', items = [] }: CardProps) {
  // variant et items ne seront JAMAIS undefined
  return (
    <div className={variant === 'primary' ? 'bg-blue-500' : 'bg-gray-500'}>
      <h2>{title}</h2>
      {items.map(item => <p key={item}>{item}</p>)}
    </div>
  )
}

// Nullish coalescing : valeur de secours
const name = user?.name ?? "Inconnu"
const count = data?.total ?? 0
const items = response?.results ?? []

8.5Bouclier 5 : Le error boundary React

Error Boundary : capturer les crashes Reacttsx
// app/error.tsx - Error Boundary automatique Next.js
'use client'

export default function Error({
  error,
  reset,
}: {
  error: Error & { digest?: string }
  reset: () => void
}) {
  return (
    <div className="text-center py-20">
      <h2 className="text-2xl font-bold mb-4">Oups, quelque chose s'est mal passe</h2>
      <p className="text-gray-600 mb-6">{error.message}</p>
      <button
        onClick={reset}
        className="bg-blue-500 text-white px-6 py-2 rounded-lg"
      >
        Reessayer
      </button>
    </div>
  )
}

// Ce fichier attrape TOUTES les erreurs de la route.
// Au lieu d'un ecran blanc, l'utilisateur voit un message propre.

8.6La checklist pre-commit

Avant chaque commit

  • Pas de console.log restant ?
  • Pas de TypeScript error (rouge souligne) ?
  • ESLint passe sans warning ?
  • Le build passe (npm run build) ?
  • Les cas edge sont geres (null, undefined, tableau vide) ?
  • Pas de donnees en dur qui devraient etre en variable d'environnement ?

Verifie tes acquis

5 questions pour valider ce chapitre

1. Pourquoi activer "strict": true dans tsconfig.json ?

Valide et sauvegarde ce chapitre

Ne perds pas le fil de ton apprentissage. Chaque QCM terminé sauvegarde ton score. Crée ton profil gratuitement pour débloquer toutes les évaluations du site et retrouver tes résultats plus tard.

Commencer l'aventure
Déjà membre ?Connecte-toi