Typescript fondamentaux
Thème :
Junior
1 vues ·4/14 leçons

04 - DOM, Events et Web APIs : TypeScript côté Navigateur (propre, sûr, maintenable)

4.1 Pourquoi TypeScript dans le navigateur change tout

Quand tu développes une UI (blog, dashboard, e-commerce), une grande partie des bugs vient de :

  • Sélecteurs DOM qui ne trouvent rien (null) mais on continue comme si l’élément existait
  • Événements mal typés (on croit avoir un input.value, mais on écoute un autre élément)
  • Données venant de formulaires ou d’APIs (toujours des string) utilisées comme des number
  • Manipulations asynchrones et timing (élément pas encore présent, état pas encore prêt)

TypeScript n’empêche pas tous les bugs, mais il impose une discipline :

  • On gère explicitement le null
  • On sait exactement quel type d’élément on manipule (bouton, input, formulaire…)
  • On écrit des fonctions réutilisables (helpers DOM, validation, parsing)
  • On évite de “deviner” ce que contient event.target

L’objectif de cette leçon : t’apprendre à écrire du code DOM qui se lit facilement, se refactorise bien, et tient dans le temps.


4.2 Le DOM en TypeScript : le point crucial (le null)

La réalité du DOM

Dans un navigateur, querySelector() et getElementById() peuvent retourner null.

En JavaScript, on oublie souvent ce cas et on obtient des erreurs du type :

  • Cannot read properties of null (reading 'addEventListener')

En TypeScript strict, c’est volontairement bloquant :

  • si tu ne gères pas null, le compilateur refuse

Stratégies propres (sans “any”)

  • Stratégie A : early return

    • tu vérifies, puis tu sors proprement
  • Stratégie B : helper assertExists

    • tu centralises l’erreur (meilleure DX)
  • Stratégie C : data-attributes + initialisation

    • tu relies les éléments par data-* (très pratique dans les projets UI)

Ce qu’il faut retenir :

  • ne pas forcer avec des assertions partout (ex: !) sans raison
  • documenter par le code ce qui est obligatoire et ce qui est optionnel

4.3 Typage des éléments HTML : connaître sa “cible”

Pourquoi c’est important

Un HTMLElement n’a pas forcément .value.

  • Un HTMLInputElement a .value
  • Un HTMLButtonElement a .disabled et .type
  • Un HTMLFormElement a .elements et .submit()

TypeScript te force à être clair :

  • soit tu sélectionnes directement le bon type
  • soit tu vérifies avant utilisation

Méthodes recommandées

  • Caster en dernier recours

    • utile quand tu as un contexte très sûr
    • à éviter si tu n’as pas le contrôle sur le DOM
  • Type guards

    • méthode la plus saine : tu verifies que c’est bien un input/bouton avant d’utiliser .value

4.4 Événements : comprendre event.target vs currentTarget

Différence essentielle

  • event.target

    • l’élément exact qui a déclenché l’événement (souvent un enfant)
  • event.currentTarget

    • l’élément sur lequel tu as attaché le listener

Dans un système de composants (ou même un simple menu), cette différence explique énormément de bugs.

Bonnes pratiques

  • si tu fais de la délégation d’événements (event delegation), tu travailleras souvent avec target
  • si tu attaches l’événement au bon élément directement, currentTarget est plus stable

4.5 Event Delegation : performance + simplicité

Pourquoi c’est une bonne idée

Quand tu as une liste dynamique (posts, commentaires, tâches), tu ne veux pas :

  • ajouter 100 listeners
  • ré-attacher des listeners à chaque re-render

Tu préfères :

  • un seul listener sur le parent
  • tu détectes sur quoi l’utilisateur a cliqué

Comment TypeScript aide

TypeScript te force à :

  • vérifier que target est un Element
  • trouver un parent avec closest()
  • lire un data-id (qui est une string) puis le convertir proprement

Résultat : moins de bugs et un code plus stable.


4.6 Formulaires : parsing, validation et typage (la vraie vie)

Problème

Tout ce qui sort d’un formulaire est une string.

Même si le champ est type="number" :

  • tu récupères une string

Objectif

Créer une “pipeline” propre :

  • lire
  • parser
  • valider
  • construire un objet typé

Bonnes pratiques

  • ne pas faire confiance à l’UI
  • ne pas faire confiance à l’utilisateur
  • ne pas faire confiance aux données réseau

TypeScript te permet de définir :

  • un type “raw” (form input)
  • un type “domaine” (ton modèle validé)

4.7 Web APIs modernes : typées, mais pas “magiques”

TypeScript apporte du typage sur les APIs du navigateur (DOM lib), mais il faut comprendre les limites :

  • le typage décrit l’API, pas la disponibilité runtime

4.7.1 Fetch API

TypeScript te donne :

  • les types de RequestInit
  • Response
  • Headers

Mais il ne garantit pas que la réponse JSON correspond à ton type. C’est ton job.

4.7.2 Storage (localStorage/sessionStorage)

  • stocke uniquement des strings
  • tu dois sérialiser/désérialiser
  • attention à la compatibilité des versions (migration)

4.7.3 Clipboard API

  • peut être bloquée par permissions
  • nécessite un contexte sécurisé (https)
  • la promesse peut échouer : gestion d’erreur obligatoire

4.7.4 IntersectionObserver / ResizeObserver

  • parfaits pour lazy-loading et UIs performantes
  • excellent combo avec TypeScript car tu structures mieux ton init

4.7.5 History / URL / URLSearchParams

  • pour des UIs SEO-friendly
  • TypeScript encourage une gestion propre des paramètres

4.8 Pattern recommandé : “init UI” + helpers DOM

Dans un projet pro, tu veux éviter le “code spaghetti” dispersé.

Pattern simple :

  • un fichier dom.ts avec helpers
  • un fichier init.ts (ou main.ts) qui initialise la page
  • chaque feature a une fonction initFeatureX()

Avantages :

  • lisible
  • testable
  • refactor-friendly

4.9 Intégration avec frameworks modernes (Vue/React)

React

En React, tu manipules moins le DOM directement, mais tu en as toujours besoin pour :

  • focus management
  • scroll
  • mesures (getBoundingClientRect)
  • IntersectionObserver

TypeScript devient crucial sur :

  • useRef<HTMLDivElement | null>
  • events typés (React.MouseEvent, React.ChangeEvent)

Vue 3

Vue 3 + TS est très courant.

Points clés :

  • ref<HTMLElement | null>(null)
  • props typées
  • emits typés
  • composables bien typés (réutilisables)

Conclusion

Même avec frameworks :

  • la compréhension DOM/events reste indispensable
  • TypeScript te donne une sécurité incroyable dans les interactions

🎯 TP 4 : Mini App “Task Board” (DOM + Events + Storage) en TypeScript

Objectif pédagogique

Construire une mini application type Trello (simplifiée) qui met en pratique :

  • sélection DOM typée
  • event delegation
  • formulaires et parsing
  • storage typé (localStorage)
  • Web APIs (drag & drop optionnel, IntersectionObserver optionnel)

Fonctionnalités requises (MVP)

1) Colonnes et tâches

  • 3 colonnes :

    • À faire
    • En cours
    • Terminé
  • une tâche contient :

    • id (string unique)
    • title (string)
    • description (string optionnel)
    • status (union type)
    • createdAt (timestamp)
    • priority (union type)

2) Ajout de tâche (formulaire)

  • champ titre obligatoire
  • description optionnelle
  • priorité
  • validation côté front (messages clairs)

3) Actions sur une tâche

  • supprimer
  • éditer (au minimum : modifier le titre)
  • déplacer (au minimum : changer de colonne via select)

4) Persistance

  • sauvegarde automatique dans localStorage
  • rechargement au refresh
  • stratégie de migration simple (si tu changes la structure plus tard)

Bonus (facultatif)

  • drag & drop
  • filtre par priorité
  • recherche textuelle
  • compteur par colonne
  • IntersectionObserver pour lazy-render si la liste grandit

Structure recommandée du projet

  • src/types.ts

    • types du domaine (Task, Status, Priority)
  • src/storage.ts

    • fonctions pour loadTasks() / saveTasks()
  • src/dom.ts

    • helpers DOM : qs(), qsa(), assertExists()
  • src/tasks.ts

    • logique métier : create/update/delete/move
  • src/ui.ts

    • rendering + gestion des events
  • src/main.ts

    • initialise tout

Critères de réussite

  • Pas de any
  • Gestion explicite de null sur le DOM
  • Events typés (pas de propriétés fantômes)
  • Parsing propre des données (form + storage)
  • Logique métier séparée du rendu
  • UI utilisable, stable, et qui survit au refresh

Livrable attendu

  • Repo avec code TypeScript + build tool (Vite recommandé)
  • Une page fonctionnelle
  • Un README qui explique :
    • comment lancer
    • la structure
    • les choix techniques

Auto-évaluation (anti-triche)

Pour t’auto-vérifier (et vérifier un élève), tu dois pouvoir répondre clairement :

  • pourquoi querySelector() retourne null et comment tu le gères
  • pourquoi event.target n’est pas toujours le bon élément
  • comment tu assures que les données localStorage correspondent au modèle
  • pourquoi tu as séparé “domaine” vs “UI”

Cette leçon te donne des réflexes très concrets : écrire du TypeScript côté DOM sans tomber dans les pièges classiques (null, types d’éléments, événements).

Prêt à passer à la suite ?

Vous avez terminé cette leçon sur 04 - DOM, Events et Web APIs : TypeScript côté Navigateur (propre, sûr, maintenable). Continuez votre apprentissage avec la prochaine leçon ou explorez d'autres formations.