Cours JavaScript et TypeScript · Module 6: Bases de TypeScript
Configuration de l'environnement (tsconfig.json)
Dans cette leçon9
Introduction : la carte du Jurassic Park
Dans la leçon précédente, nous avons découvert TypeScript comme un système de sécurité avancé pour notre Jurassic Park. Il est maintenant temps de comprendre comment configurer ce système : c'est comme concevoir une carte du parc, définir des zones de sécurité et fixer des niveaux d'accès.
Dans le monde de TypeScript, cette configuration est fournie par le fichier tsconfig.json. Il détermine le fonctionnement du compilateur TypeScript, les options activées, la rigueur des règles de typage, et bien d'autres aspects.
Le Dr Henry Wu, le généticien en chef du parc, aime dire : « Le contrôle est une illusion. » Mais dans le cas de TypeScript, une bonne configuration nous donne un véritable contrôle sur notre code.
Créer le fichier tsconfig.json
Commençons par créer un fichier de configuration de base pour notre système de gestion du Jurassic Park :
1# Si tu as TypeScript installé globalement, tu peux utiliser :
2tsc --init
3
4# Ou en utilisant npx :
5npx tsc --initCette commande génère un fichier tsconfig.json de base avec les options les plus importantes (la plupart d'entre elles seront commentées). Pour notre parc à dinosaures, nous pouvons créer une configuration personnalisée :
1{
2 "compilerOptions": {
3 "target": "es2016",
4 "module": "commonjs",
5 "outDir": "./dist",
6 "rootDir": "./src",
7 "strict": true,
8 "esModuleInterop": true,
9 "skipLibCheck": true,
10 "forceConsistentCasingInFileNames": true
11 },
12 "include": ["src/**/*"],
13 "exclude": ["node_modules", "**/*.spec.ts"]
14}C'est comme si le Dr Hammond avait préparé des directives sur la façon dont les différentes zones du parc doivent fonctionner.
Les options de configuration les plus importantes
Structure de base du projet
Tout comme nous devons désigner dans le parc des zones pour différentes espèces de dinosaures, dans un projet TypeScript nous devons définir où se trouvent les fichiers source et où les fichiers de sortie seront générés :
1{
2 "compilerOptions": {
3 "outDir": "./dist", // Répertoire de sortie où les fichiers .js seront générés
4 "rootDir": "./src", // Répertoire source où se trouvent les fichiers .ts
5 "baseUrl": ".", // URL de base pour les chemins relatifs
6 "paths": { // Alias pour les chemins d'import
7 "@models/*": ["src/models/*"],
8 "@utils/*": ["src/utils/*"],
9 "@config/*": ["src/config/*"]
10 }
11 }
12}C'est comme avoir une carte du parc avec des repères :
- « src » est notre base opérationnelle principale
- « dist » est la zone accessible aux visiteurs
- Nous avons aussi des raccourcis vers des endroits importants du parc (laboratoire, centre de contrôle, etc.)
Version d'ECMAScript
Tout comme le parc doit être compatible avec différentes espèces de dinosaures, notre code TypeScript doit être compatible avec différents environnements JavaScript :
1{
2 "compilerOptions": {
3 "target": "es2016", // Vers quelle version de JS compiler
4 "module": "commonjs", // Système de modules (commonjs, modules ES, etc.)
5 "lib": ["dom", "es2016", "dom.iterable", "scripthost"] // Bibliothèques de définitions
6 }
7}Dans notre parc :
- « target » revient à préciser avec quelles espèces de dinosaures nous sommes capables de travailler
- « module » est comme le système de transport du parc (jeeps, monorail, etc.)
- « lib » revient à préciser quels outils et équipements nous avons à disposition
Niveau de rigueur
Selon les espèces de dinosaures présentes dans le parc, nous avons besoin de niveaux de sécurité différents. De même en TypeScript, nous pouvons régler le niveau de rigueur de la vérification des types :
1{
2 "compilerOptions": {
3 "strict": true, // Active toutes les options strictes ci-dessous
4 "noImplicitAny": true, // Exige une déclaration explicite du type "any"
5 "strictNullChecks": true, // Exige la vérification de null et undefined
6 "strictFunctionTypes": true, // Vérification plus stricte des types de fonctions
7 "strictBindCallApply": true, // Vérification de type pour les méthodes bind, call et apply
8 "strictPropertyInitialization": true, // Vérifie que les propriétés de classe sont initialisées
9 "noImplicitThis": true, // Exige un type explicite pour "this"
10 "alwaysStrict": true // Analyse le code en mode strict
11 }
12}Dans le contexte du Jurassic Park :
strict: truerevient à mettre en place le niveau de sécurité le plus élevé dans tous les secteurs du parcnoImplicitAnyest comme la règle « toujours identifier l'espèce du dinosaure avant de le placer dans un enclos »strictNullChecksrevient à vérifier que les clôtures sont vraiment branchées au courant au lieu de supposer que tout fonctionne
Configuration des modules et des imports
Pour gérer le parc, nous avons besoin d'un système de communication clair entre les différents services. En TypeScript, nous configurons la façon dont les modules communiquent entre eux :
1{
2 "compilerOptions": {
3 "module": "esnext", // Système de modules
4 "moduleResolution": "node", // Stratégie de résolution des modules
5 "esModuleInterop": true, // Meilleure interopérabilité avec les modules CommonJS
6 "allowSyntheticDefaultImports": true, // Autorise l'import par défaut depuis des modules sans export par défaut
7 "resolveJsonModule": true // Autorise l'import de fichiers JSON
8 }
9}Dans le parc :
moduleResolutionest comme le système de communication radio : il définit comment nous trouvons et contactons les différentes équipesesModuleInteroprevient à s'assurer que les anciens et les nouveaux systèmes de communication fonctionnent ensembleresolveJsonModuleest comme la capacité de lire des formulaires de rapport standard
Options pour les développeurs
Le Dr Wu a besoin d'outils pour créer de nouvelles espèces de dinosaures. Nous avons nous aussi besoin d'outils de développement :
1{
2 "compilerOptions": {
3 "sourceMap": true, // Génère des fichiers .map pour faciliter le débogage
4 "declaration": true, // Génère des fichiers .d.ts avec les déclarations de types
5 "declarationMap": true, // Génère des fichiers .map pour les fichiers .d.ts
6 "incremental": true, // Accélère la compilation en mettant en cache les builds précédents
7 "tsBuildInfoFile": "./dist/.tsbuildinfo" // Fichier contenant les infos de compilation
8 }
9}Dans le parc :
sourceMapest comme une documentation ADN détaillée pour chaque dinosaure : elle aide à comprendre ce qui a mal tournédeclarationest comme un registre de toutes les espèces de dinosauresincrementalrevient à optimiser le processus de clonage pour éviter de répéter les mêmes procédures
Options pour les projets React
Si tu utilises React (de façon hypothétique, des attractions interactives dans le Jurassic Park), des options supplémentaires sont utiles :
1{
2 "compilerOptions": {
3 "jsx": "react", // Prise en charge de la syntaxe JSX
4 "jsxFactory": "React.createElement", // Fonction utilisée pour compiler le JSX
5 "jsxFragmentFactory": "React.Fragment" // Composant Fragment
6 }
7}C'est comme configurer des écrans interactifs dans le centre d'accueil des visiteurs qui montrent des animations et des informations sur les dinosaures.
Configuration pour des cas spécifiques
Projet Node.js pour le système de sécurité du parc
1{
2 "compilerOptions": {
3 "target": "es2018",
4 "module": "commonjs",
5 "outDir": "./dist",
6 "rootDir": "./src",
7 "strict": true,
8 "esModuleInterop": true,
9 "skipLibCheck": true,
10 "forceConsistentCasingInFileNames": true,
11 "lib": ["es2018"]
12 },
13 "include": ["src/**/*"],
14 "exclude": ["node_modules", "**/*.spec.ts"]
15}Application frontend pour le tableau de bord de gestion du parc
1{
2 "compilerOptions": {
3 "target": "es5",
4 "lib": ["dom", "dom.iterable", "esnext"],
5 "allowJs": true,
6 "skipLibCheck": true,
7 "esModuleInterop": true,
8 "allowSyntheticDefaultImports": true,
9 "strict": true,
10 "forceConsistentCasingInFileNames": true,
11 "module": "esnext",
12 "moduleResolution": "node",
13 "resolveJsonModule": true,
14 "isolatedModules": true,
15 "noEmit": true,
16 "jsx": "react"
17 },
18 "include": ["src"]
19}Étendre la configuration
Dans un grand parc à dinosaures, il peut y avoir différentes zones avec leurs propres règles de sécurité, mais toutes sont soumises à des règles générales. De même, en TypeScript, nous pouvons étendre les configurations :
1// tsconfig.base.json - configuration principale
2{
3 "compilerOptions": {
4 "target": "es2016",
5 "module": "commonjs",
6 "strict": true
7 }
8}
9
10// tsconfig.backend.json - configuration backend
11{
12 "extends": "./tsconfig.base.json",
13 "compilerOptions": {
14 "outDir": "./dist/backend",
15 "rootDir": "./src/backend"
16 },
17 "include": ["src/backend/**/*"]
18}
19
20// tsconfig.frontend.json - configuration frontend
21{
22 "extends": "./tsconfig.base.json",
23 "compilerOptions": {
24 "outDir": "./dist/frontend",
25 "rootDir": "./src/frontend",
26 "jsx": "react"
27 },
28 "include": ["src/frontend/**/*"]
29}C'est comme une carte du parc avec différentes zones qui partagent des règles de sécurité communes mais ont aussi leurs propres directives spécifiques.
Exemple pratique : système de surveillance du Jurassic Park
Imaginons que nous créons un nouveau système de surveillance pour le parc ; voici la configuration que nous pourrions utiliser :
1{
2 "compilerOptions": {
3 // Version ES
4 "target": "es2018",
5 "module": "commonjs",
6 "lib": ["es2018", "dom"],
7
8 // Structure du projet
9 "outDir": "./dist",
10 "rootDir": "./src",
11 "baseUrl": ".",
12 "paths": {
13 "@park/*": ["src/park/*"],
14 "@security/*": ["src/security/*"],
15 "@monitoring/*": ["src/monitoring/*"],
16 "@types/*": ["src/types/*"]
17 },
18
19 // Rigueur
20 "strict": true,
21 "noImplicitAny": true,
22 "strictNullChecks": true,
23
24 // Gestion des modules
25 "moduleResolution": "node",
26 "esModuleInterop": true,
27 "resolveJsonModule": true,
28
29 // Outils de développement
30 "sourceMap": true,
31 "declaration": true,
32
33 // Règles supplémentaires
34 "forceConsistentCasingInFileNames": true,
35 "skipLibCheck": true,
36 "noUnusedLocals": true,
37 "noUnusedParameters": true
38 },
39 "include": ["src/**/*"],
40 "exclude": ["node_modules", "dist", "**/*.spec.ts"]
41}Avec ce fichier de configuration, notre système de sécurité du Jurassic Park serait :
- Moderne et compatible avec les standards actuels (
es2018) - Bien organisé, avec une structure de répertoires claire
- Strict dans la vérification des types, ne laissant passer aucune vulnérabilité potentielle
- Flexible dans la gestion des modules et des dépendances
- Facile à déboguer et doté d'une bonne documentation des types
- Exempt de variables et de paramètres inutilisés qui pourraient prêter à confusion
Outils complémentaires
Au-delà du fichier tsconfig.json lui-même, il vaut aussi la peine de configurer des outils complémentaires qui facilitent le travail avec TypeScript :
ESLint pour TypeScript
ESLint est comme un système de surveillance supplémentaire dans le parc qui détecte les menaces potentielles :
1// .eslintrc.json
2{
3 "parser": "@typescript-eslint/parser",
4 "plugins": ["@typescript-eslint"],
5 "extends": [
6 "eslint:recommended",
7 "plugin:@typescript-eslint/recommended"
8 ],
9 "rules": {
10 "no-console": "warn",
11 "@typescript-eslint/explicit-function-return-type": "error",
12 "@typescript-eslint/no-explicit-any": "error"
13 }
14}Prettier pour le formatage du code
Prettier est comme un code vestimentaire et un code de conduite pour les employés du parc : tout le monde a la même apparence et agit de manière cohérente :
1// .prettierrc
2{
3 "semi": true,
4 "trailingComma": "all",
5 "singleQuote": true,
6 "printWidth": 100,
7 "tabWidth": 2
8}Problèmes courants et solutions
Problème : « Property 'x' does not exist on type 'y' »
Cette erreur est comme le système de sécurité qui sonne l'alarme parce que tu essaies d'utiliser un code d'accès inexistant pour un enclos :
1// Erreur
2const dino = { species: "T-Rex", age: 5 };
3console.log(dino.height); // Erreur : Property 'height' does not exist on type '{ species: string; age: number; }'.
4
5// Solution 1 : ajouter la propriété au type
6const dino: { species: string; age: number; height?: number } = {
7 species: "T-Rex",
8 age: 5
9};
10
11// Solution 2 : utiliser une interface
12interface Dinosaur {
13 species: string;
14 age: number;
15 height?: number;
16}
17const dino: Dinosaur = { species: "T-Rex", age: 5 };Problème : la configuration n'est pas appliquée
Parfois, comme lorsque le système de sécurité du parc ne répond pas, la configuration de TypeScript peut ne pas être correctement appliquée :
- Vérifie que les chemins dans
includeetexcludesont corrects - Assure-toi d'utiliser le bon fichier tsconfig.json
- Redémarre le serveur TypeScript dans ton IDE
1# Vérifier quels fichiers sont traités par TypeScript
2tsc --listFiles
3
4# Vérifier si le compilateur trouve tsconfig.json
5tsc --showConfigProblème : types manquants pour une bibliothèque externe
C'est comme découvrir qu'il manque la documentation d'un nouvel équipement de sécurité dans le parc :
1# Essaie de trouver les définitions de types pour la bibliothèque
2npm install --save-dev @types/library-name
3
4# S'il n'existe pas de types officiels, crée les tiens
5touch src/types/library-name.d.ts1// src/types/library-name.d.ts
2declare module 'library-name' {
3 export function function1(param: string): number;
4 export function function2(param: number): string;
5 export const constant: string;
6}Résumé
Le fichier tsconfig.json est comme une carte du Jurassic Park : il définit les zones, les niveaux de sécurité et les directives pour tous les systèmes. Une bonne configuration de TypeScript garantit :
- Un code cohérent dans tout le projet
- Une détection précoce des problèmes potentiels
- Une meilleure prise en charge des outils de développement
- Des règles claires pour toute l'équipe de programmation
Tout comme John Hammond n'a ménagé aucune dépense pour la sécurité du parc, nous ne devrions pas faire l'impasse sur une bonne configuration de TypeScript. C'est un investissement qui se traduit par un code plus stable et plus sûr.
Dans la prochaine leçon, nous nous pencherons sur le compilateur TypeScript et apprendrons comment il transforme le code TypeScript en JavaScript, un peu comme les scientifiques du laboratoire transforment l'ADN en dinosaures vivants !
Code de cette leçon : tsconfig.json
1{
2 "compilerOptions": {
3 /* Language and Environment */
4 "target": "ES2020",
5 "lib": ["ES2020", "DOM"],
6 "module": "commonjs",
7 "moduleResolution": "node",
8
9 /* Output */
10 "outDir": "./dist",
11 "rootDir": "./src",
12 "removeComments": true,
13 "sourceMap": true,
14
15 /* Type Checking */
16 "strict": true,
17 "noImplicitAny": true,
18 "strictNullChecks": true,
19 "strictFunctionTypes": true,
20 "noUnusedLocals": true,
21 "noUnusedParameters": true,
22 "noImplicitReturns": true,
23
24 /* Interop Constraints */
25 "esModuleInterop": true,
26 "allowSyntheticDefaultImports": true,
27 "forceConsistentCasingInFileNames": true,
28
29 /* Skip Library Check */
30 "skipLibCheck": true
31 },
32 "include": ["src/**/*"],
33 "exclude": ["node_modules", "dist", "**/*.spec.ts"]
34}Tu as repéré une erreur dans cette leçon ?
Teste tes connaissances
Réponds aux questions de cette leçon. Choisis une réponse pour voir tout de suite si elle est correcte.
1. Que spécifie l’option 'target' dans tsconfig.json ?
2. À quoi servent les options 'include' et 'exclude' dans tsconfig.json ?
Tâches pratiques dans le jeu
- Éditeur de code
Complète le fichier tsconfig.json avec les options strict, target et outDir.