1.1 · Hello world TypeScript
Les diapositives de la séance 1
- transpiler un fichier TypeScript en JavaScript et l’exécuter
- expliquer ce qu’est la transpilation et en quoi elle diffère de la compilation
- utiliser les types de base :
string,number,boolean, tableaux, tuples - écrire des chaînes avec les template literals
- dire à quoi sert concrètement le typage statique
Node.js, npm et TypeScript installés : voir Démarrage.
Récupérer le code du cours
Chaque exemple est téléchargeable depuis la page qui le présente, et le code montré dans les blocs se copie d’un clic avec l’icône en haut à droite.
Pour ce chapitre : télécharger hello.ts. Placez-le dans un dossier de travail, et c’est tout.
Votre premier fichier TypeScript
Voici l’essentiel de hello.ts :
hello.ts
// 1. STRING : chaîne de caractères
const message: string = "Hello World";
const prenom: string = 'Alice'; // guillemets simples ou doubles
console.log(message, prenom);
// 2. NUMBER : entiers et décimaux, un seul type pour les deux
const age: number = 25;
const prix: number = 19.99;
const negatif: number = -10;
const hexadecimal: number = 0xff; // 255
// 3. BOOLEAN : vrai ou faux
const estActif: boolean = true;
// 4. ARRAY : deux syntaxes équivalentes
const nombres: number[] = [1, 2, 3, 4, 5];
const fruits: Array<string> = ["pomme", "banane", "orange"];La nouveauté par rapport à JavaScript tient dans les : string, : number, : boolean. Ce sont des annotations de type : elles indiquent au compilateur ce que chaque variable a le droit de contenir.
Transpiler et exécuter
1. Transpiler : traduire le TypeScript en JavaScript :
tsc hello.tsUn fichier hello.js apparaît à côté de hello.ts.
2. Exécuter le JavaScript produit, sans navigateur :
node hello.jsCinq commandes à ne pas confondre
Vous venez de taper tsc puis node. Il en existe trois autres qui se ressemblent beaucoup, et les confondre fait perdre un temps considérable. Voici la carte complète.
| Commande | Nom complet | Ce qu’elle fait |
|---|---|---|
node |
Node.js | exécute du JavaScript en dehors du navigateur |
npm |
Node Package Manager | installe des paquets, lance les scripts du projet |
npx |
Node Package eXecute | lance un outil installé dans le projet |
tsc |
TypeScript Compiler | traduit .ts → .js |
tsx |
TypeScript eXecute | traduit et exécute un .ts d’un seul coup |
Qui fait quoi, dans l’ordre
Un fichier TypeScript ne s’exécute jamais directement. Il y a toujours deux temps :
hello.ts ──(tsc)──> hello.js ──(node)──> résultat affiché
│ ^
└──────────────────(tsx)───────────────────────┘
les deux d'un coup
tsx ne fait rien de magique : il traduit en mémoire, puis exécute. Il ne laisse simplement aucun .js sur le disque.
node et npm : installés ensemble, rôles opposés
Vous installez Node.js une fois sur votre machine, et npm arrive avec.
nodefait tourner du code.node hello.jsexécute le fichier.npmne fait tourner aucun code à vous. Il télécharge des paquets depuis internet et les range dans le dossiernode_modulesdu projet.
npm install typescript --save-dev # telecharge le paquet dans ce projet--save-dev ?
Le paquet est nécessaire pour développer (traduire votre code), pas pour faire tourner le résultat. --save-dev le note dans la catégorie « outils de développement » du package.json. Sans conséquence pour vous à ce stade, mais c’est la bonne habitude.
npx : le pont entre npm et les outils
Quand npm install place typescript dans node_modules, la commande tsc n’existe pas pour autant dans votre terminal : elle est enfouie dans le projet, pas connue du système.
npx sert exactement à ça : trouver et lancer un outil installé dans le projet.
npx tsc hello.tsnpx cherche tsc dans le node_modules du dossier courant. S’il ne l’y trouve pas, il le télécharge temporairement, l’exécute, et ne l’installe nulle part.
Retenez la règle en une phrase :
- installé globalement sur votre machine → tapez
tsc - installé dans le projet → tapez
npx tsc
C’est le même programme dans les deux cas. npx n’est qu’un moyen de le retrouver.
Les quatre combinaisons
| Commande | Ce qui se passe | Fichier .js créé ? |
|---|---|---|
tsc hello.ts |
traduit, avec le TypeScript global | oui |
npx tsc hello.ts |
traduit, avec le TypeScript du projet | oui |
tsx hello.ts |
traduit et exécute, TypeScript global | non |
npx tsx hello.ts |
traduit et exécute, TypeScript du projet | non |
Autrement dit : npx répond à « où est l’outil ? », tsc/tsx répondent à « qu’est-ce que j’en fais ? ». Les deux questions sont indépendantes.
tsc et tsx ne diffèrent que d’une lettre et font des choses différentes.
tsc hello.tsne produit qu’un fichier. Rien ne s’affiche : c’est normal, vous n’avez encore rien exécuté. Il faut ensuitenode hello.js.tsx hello.tsaffiche directement le résultat, mais ne laisse aucun fichier.
Si vous ne voyez rien s’afficher, vérifiez d’abord laquelle des deux vous avez tapée.
Vous n’avez pas le droit d’installer globalement : tsc et tsx seuls répondront command not found. Préfixez systématiquement par npx, depuis le dossier du projet où vous avez fait npm install.
Dans tout le reste du cours, quand vous lisez tsc, comprenez npx tsc.
Raccourci : exécuter sans transpiler à la main
npm install tsx --save-dev
npx tsx hello.tsPratique pour expérimenter. Gardez toutefois tsc en tête : c’est lui qui vérifie les types et signale les erreurs, et c’est cette vérification qui fait tout l’intérêt de TypeScript.
Transpilation ou compilation ?
Les deux traduisent du code, mais pas vers la même cible :
| Entrée | Sortie | |
|---|---|---|
| Compilation (gcc sur du C) | code source | code binaire, exécutable par le processeur |
| Transpilation (tsc sur du TypeScript) | code source | code source dans un autre langage |
tsc produit donc du JavaScript lisible, que vous pouvez ouvrir.
Exercice 1.1 : Observer la transpilation
essentiel
Ouvrez hello.ts et hello.js côte à côte dans VS Code (clic droit sur un onglet → Split Right).
- Qu’est devenu
const message: string = "Hello World";? - Cherchez une seule annotation de type qui aurait survécu dans le
.js. Conclusion ? - À quel moment les erreurs de type sont-elles détectées, alors ?
1. L’annotation a disparu. La ligne est devenue :
var message = "Hello World";Deux transformations se sont produites, et il faut bien les distinguer. La disparition du : string est le cœur du sujet. Le passage de const à var, lui, n’a rien à voir avec les types : c’est la conséquence de la cible de transpilation. Par défaut tsc vise ES5, une version ancienne de JavaScript qui ignore const et les template literals. Avec tsc --target es2020 hello.ts, vous garderez const et les backticks, mais l’annotation de type, elle, disparaîtra toujours.
2. Vous n’en trouverez aucune, et c’est exactement la conclusion attendue : le JavaScript produit ne contient plus aucune trace du système de types. Les annotations n’existent qu’à l’écriture, pour le compilateur et pour l’éditeur. À l’exécution, il ne reste que du JavaScript ordinaire, qui accepterait sans broncher message = 42.
On dit que les types de TypeScript sont effacés (type erasure). C’est aussi ce qui explique qu’ils ne coûtent rien en performance : il n’y a aucune vérification de type pendant l’exécution.
3. Puisqu’il ne reste rien à vérifier à l’exécution, les erreurs de type sont nécessairement détectées avant, au moment où tsc lit votre fichier, autrement dit à l’écriture, puisque VS Code lance la même analyse en continu et souligne la faute pendant que vous tapez.
Le point clé : cette question paraît anecdotique, elle décide en réalité de tout l’usage de TypeScript. Les types ne vous protègent pas au moment où votre programme tourne : ils ne peuvent rien contre une donnée mal formée arrivant d’une API ou d’un formulaire. Ils vous protègent contre les incohérences de votre propre code, et cette protection s’arrête net à la frontière du programme. C’est la raison d’être du type unknown et des vérifications manuelles que vous écrirez au chapitre 5.1 · JSON.
L’erreur classique : croire que tsc refuse de produire le .js quand il trouve une erreur. Il la signale, puis génère le fichier quand même. Ajoutez "noEmitOnError": true dans tsconfig.json si vous voulez qu’il s’arrête vraiment.
Les template literals
Écrites avec des backticks `, elles remplacent avantageusement la concaténation.
| Clavier | Combinaison |
|---|---|
| AZERTY Windows / Linux | AltGr + 7 |
| AZERTY Mac | Option + è (parfois Option + 7) |
| QWERTY | touche à gauche du 1 |
Sur Mac comme sur PC, le backtick est une touche morte : rien ne s’affiche tant que vous ne tapez pas la touche suivante. Tapez-la deux fois pour obtenir deux backticks, puis revenez entre les deux.
const nom: string = "Alice";
const age: number = 25;
// Concaténation : lourde et facile à casser
const phrase1: string = "Bonjour " + nom + ", tu as " + age + " ans.";
// Template literal : on lit la phrase telle qu'elle s'affichera
const phrase2: string = `Bonjour ${nom}, tu as ${age} ans.`;Trois usages qui justifient à eux seuls de les adopter :
// 1. Calculer dans ${}
const prixHT: number = 100;
const tva: number = 20;
console.log(`Total TTC : ${prixHT + tva}€`);
// 2. Appeler une méthode dans ${}
const ville: string = "paris";
console.log(`La capitale est ${ville.toUpperCase()}`); // PARIS
// 3. Écrire sur plusieurs lignes : impossible avec "" ou ''
const poeme: string = `Roses are red,
Violets are blue,
TypeScript is awesome`;Le symbole $ seul ne suffit pas : `Bonjour $nom` affiche littéralement Bonjour $nom. Il faut les accolades : `Bonjour ${nom}`.
toFixed renvoie une chaîne
Pour afficher un nombre avec un nombre fixe de décimales, on utilise toFixed :
const nombre: number = 3.14159265359;
console.log(nombre.toFixed(2)); // "3.14" : une string, pas un numbertoFixed(n) arrondit à n décimales et renvoie une string. Pratique pour l’affichage, dangereux pour un calcul : nombre.toFixed(2) + 1 donne "3.141" et non 4.14. Revenez à un nombre avec Number(...) si vous devez recalculer.
Le système de types
Types composés
| Type | Description | Exemple |
|---|---|---|
| tableau | éléments de même type, taille libre | number[] ou Array<number> |
| tuple | taille et types fixés position par position | [string, number] |
| enum | ensemble de constantes nommées | enum Couleur { Rouge, Vert } |
// Un tuple impose l'ordre : nom puis âge, pas l'inverse
const personne: [string, number] = ["Alice", 25];Types spéciaux
| Type | Sens | Quand l’utiliser |
|---|---|---|
void |
ne retourne rien | fonctions appelées pour leur effet |
null |
absence voulue de valeur | let x: null = null; |
undefined |
valeur jamais affectée | rarement écrit à la main |
unknown |
type inconnu mais sûr | données venant de l’extérieur (JSON, réseau) |
any |
désactive toute vérification | presque jamais : à éviter |
never |
ne retourne jamais | fonction qui lève toujours une erreur |
any fait taire le compilateur, et c’est exactement le problème : vous perdez la totalité du bénéfice de TypeScript sur cette variable. Quand vous ne connaissez pas le type, utilisez unknown : il vous oblige à vérifier avant d’utiliser la valeur, ce qui est précisément ce que vous voulez.
Types avancés
| Notation | Nom | Exemple |
|---|---|---|
| |
union | let id: string | number; |
type |
alias | type Point = { x: number; y: number }; |
“a” | “b” |
types littéraux | type Direction = “nord” | “sud”; |
Les types littéraux sont remarquablement utiles : Direction n’accepte que ces deux chaînes, et l’éditeur vous les propose automatiquement.
Annoter ou laisser deviner ?
const age: number = 25; // annotation explicite
const nom = "Alice"; // inférence : TypeScript déduit `string`Les deux sont corrects. Annotez explicitement tant que vous débutez : cela force à réfléchir au type et rend les erreurs plus lisibles. Les développeurs expérimentés laissent souvent l’inférence faire le travail sur les cas évidents, mais annotent toujours les signatures de fonctions.
À quoi sert vraiment le typage ?
- Les erreurs apparaissent à l’écriture, pas en production.
tscrefuse de transpiler du code incohérent. - L’autocomplétion devient fiable : l’éditeur connaît le type, donc les méthodes disponibles.
- Les types documentent le code, et contrairement aux commentaires, ils ne mentent jamais : le compilateur les vérifie.
- Le renommage devient sûr : l’éditeur retrouve tous les usages réels.
Pour approfondir : TypeScript en 5 minutes.
Vous venez du C ?
| Concept | C | TypeScript |
|---|---|---|
| Variable | int age = 25; |
const age: number = 25; |
| Chaîne | char* nom = "Alice"; |
const nom: string = "Alice"; |
| Tableau | int tab[5] = {1,2,3,4,5}; |
const tab: number[] = [1,2,3,4,5]; |
| Booléen | int flag = 1; |
const flag: boolean = true; |
| Fonction | int add(int a, int b) |
function add(a: number, b: number): number |
| Affichage | printf("Hello %d", x); |
console.log(`Hello ${x}`); |
Les différences qui surprennent le plus :
- on déclare avec
const(ne change plus) oulet(peut changer), jamais avec le type ; - le type s’écrit après le nom, précédé de
:; - pas de pointeurs, et les tableaux grandissent tout seuls ;
- un seul type
number: pas de distinctionint/float; stringest un vrai type, pas un tableau de caractères.
const par défaut
Déclarez tout en const, et ne passez à let que lorsque le compilateur se plaint. Une variable qui ne change pas est une variable qui ne peut pas causer de bug.
Exercices
Exercice 1.2 : Fiche d’identité d’une école
essentiel transfert
Créez un fichier exercice01.ts qui :
- déclare une constante
NOM_ECOLEde typestringvalant"Télécom Paris"; - déclare une variable
nombreEtudiantsde typenumber; - déclare un tableau
matieresd’au moins trois noms de matières ; - définit une fonction
afficherInfosqui prend un nom (string) et un nombre d’étudiants (number), retournevoid, et afficheL'école Télécom Paris compte 800 étudiants: écrivez-la deux fois, une fois par concaténation et une fois avec un template literal ; - appelle cette fonction ;
- affiche le nombre de matières avec
.length.
tsc exercice01.ts && node exercice01.jsexercice01.ts
// 1. Une constante : sa valeur ne changera jamais
const NOM_ECOLE: string = "Télécom Paris";
// 2. Une variable : let, parce qu'un effectif est susceptible de changer
let nombreEtudiants: number = 800;
// 3. Un tableau de chaînes
const matieres: string[] = ["Mathématiques", "Informatique", "Physique", "Réseaux"];
// 4. La fonction : void, car elle affiche mais ne renvoie rien
function afficherInfos(nomEcole: string, nbEtudiants: number): void {
// Version par concaténation : notez les espaces à l'intérieur des guillemets
console.log("L'école " + nomEcole + " compte " + nbEtudiants + " étudiants");
// Version template literal : la phrase se lit telle qu'elle s'affichera
console.log(`L'école ${nomEcole} compte ${nbEtudiants} étudiants`);
}
// 5. Appel
afficherInfos(NOM_ECOLE, nombreEtudiants);
// 6. Nombre de matières
console.log(`Nombre de matières : ${matieres.length}`);L'école Télécom Paris compte 800 étudiants
L'école Télécom Paris compte 800 étudiants
Nombre de matières : 4
Le point clé : les deux versions de la phrase produisent exactement la même sortie, et c’est précisément ce qui rend la comparaison parlante. Dans la version concaténée, les espaces sont dans les guillemets : " compte " et non "compte". Un espace oublié donne L'écoleTélécom Pariscompte, et rien ne vous le signalera, ni le compilateur, ni l’exécution. Le template literal supprime la question : vous écrivez la phrase d’un trait, les espaces sont là où vous les voyez.
Remarquez aussi la concaténation "… compte " + nbEtudiants. nbEtudiants est un number, pas une string, et TypeScript l’accepte pourtant : + entre une chaîne et un nombre convertit automatiquement le nombre en chaîne. Cette tolérance est confortable ici, elle est la source d’innombrables bugs ailleurs : "1" + 1 vaut "11", pas 2.
Sur le choix const / let : NOM_ECOLE et matieres sont en const, nombreEtudiants en let parce que l’énoncé dit « variable ». Notez au passage que const sur un tableau interdit de remplacer le tableau (matieres = [...] est refusé) mais pas de le modifier (matieres.push("Anglais") passe très bien).
Exercice 1.3 : Provoquer des erreurs volontairement
essentiel
L’objectif est d’apprendre à lire les messages de tsc. Dans un fichier erreurs.ts, écrivez ces quatre lignes, transpilez après chacune, et notez le message :
const a: number = "42";
const b: string[] = ["x", 3];
const c: [string, number] = [25, "Alice"];
const d: number = 10;
d = 20;Pour chacune : que dit le message, et quelle est la correction ?
Celle-là ne parle pas de types du tout. Relisez l’encadré sur const.
Ligne 1 : const a: number = "42";
error TS2322: Type 'string' is not assignable to type 'number'.
Vous avez promis un nombre, vous fournissez une chaîne. Les guillemets font toute la différence : "42" est du texte qui ressemble à un nombre. Correction : const a: number = 42; Si la valeur vient réellement d’un texte, convertissez : const a: number = Number("42");
Ligne 2 : const b: string[] = ["x", 3];
error TS2322: Type 'number' is not assignable to type 'string'.
Le message ne parle pas du tableau mais de l’élément fautif : string[] signifie « tableau dont tous les éléments sont des chaînes ». Correction : ["x", "3"]. Si vous vouliez vraiment mélanger, le type est (string | number)[].
Ligne 3 : const c: [string, number] = [25, "Alice"];
error TS2322: Type 'number' is not assignable to type 'string'.
error TS2322: Type 'string' is not assignable to type 'number'.
Deux erreurs, une par position. C’est là toute la différence entre un tuple et un tableau : le tuple fixe le type case par case. Les valeurs sont correctes, c’est leur ordre qui est inversé. Correction : ["Alice", 25].
Lignes 4 et 5 : const d: number = 10; puis d = 20;
error TS2588: Cannot assign to 'd' because it is a constant.
Aucun type en cause : 20 est bien un number. Le problème est le const, qui interdit toute réaffectation. Correction : let d: number = 10;
Le point clé : les messages de tsc se lisent toujours dans le même sens : « Type A n’est pas assignable au type B » signifie « vous fournissez un A là où un B est attendu ». A est ce que vous avez écrit, B ce que vous avez promis. Une fois cette lecture acquise, la quasi-totalité des erreurs de TypeScript deviennent immédiates.
Deux réflexes à prendre dès maintenant : lisez le numéro de ligne et de colonne, qui pointent l’élément exact et non la déclaration entière ; et ne vous arrêtez pas à la première erreur, tsc les affiche toutes d’un coup.
L’erreur classique : constater que hello.js a quand même été produit et en conclure que « ça marche ». tsc signale les erreurs puis génère le fichier malgré tout. Le JavaScript obtenu est parfaitement exécutable, simplement il fait ce que vous avez écrit et non ce que vous vouliez.
QCM
1. Qu’affiche le terminal après tsc hello.ts, si le fichier ne contient aucune erreur ?
A. Le résultat du programme. B. Rien : tsc produit hello.js sans l’exécuter. C. Le contenu de hello.js. D. Une erreur, car il faut d’abord lancer node.
B. tsc traduit, il n’exécute rien. Pour voir le résultat : node hello.js, ou tsx hello.ts qui fait les deux d’un coup.
2. Que reste-t-il de l’annotation : number de const age: number = 25; dans le fichier JavaScript produit ?
A. Elle est recopiée telle quelle. B. Elle devient un commentaire. C. Rien : les types sont effacés à la transpilation. D. Un test, exécuté au lancement, qui vérifie que age est un nombre.
C. Les types ne servent qu’au moment d’écrire et de transpiler le code. À l’exécution, plus rien ne les vérifie.
3. Qu’affiche ce code ?
const nom = "Alice";
console.log(`Bonjour $nom`);A. Bonjour Alice B. Bonjour $nom C. Une erreur de compilation. D. Bonjour undefined
B. Sans accolades, $nom est du texte ordinaire. Il faut écrire ${nom}.
À retenir
tsc fichier.ts→ produitfichier.js·node fichier.js→ l’exécute- Les types disparaissent à la transpilation : ils servent au moment d’écrire le code
`texte ${variable}`avec des backticks, et non"texte " + variableconstpar défaut,letseulement si la valeur doit changerunknownplutôt queany