Tableaux · Tuples · Union Types · Narrowing
Typer le contenu de vos tableaux · Structurer des données complexes · Raisonner sur des types multiples
1. Tableaux typés
Savoir écrire number[] et Array<number>
2. Tuples
Comprendre [string, number] et quand les utiliser
3. Union Types
Maîtriser string | number et string | null
4. Type Narrowing
Savoir restreindre un type avec typeof
1. Recap J2
Types primitifs, annotations de fonctions, any vs unknown
2. Tableaux typés
number[] vs Array<number> — protéger le contenu
3. Tuples
[string, number] — taille fixe, types précis
4. Union Types
string | number — le OU des types
5. Type Narrowing avec typeof
TypeScript suit ta logique dans les if/else
Recap J2
Types primitifs · annotations de fonctions · any vs unknown
Types primitifs
const nom: string = "Alice"
const age: number = 30
const actif: boolean = true
Annotations de fonctions
function saluer(
nom: string
): string {
return `Bonjour ${nom}!`
}
any vs unknown
✗ any — dangereux
let val: any = "texte"
val.toFixed() // pas d'erreur !
✓ unknown — sécurisé
let val: unknown = "texte"
if (typeof val === "number") {
val.toFixed() // OK
}
Aujourd'hui on monte d'un niveau : les structures de données
Tableaux typés
number[] vs Array<number> — protéger le contenu
En TypeScript, on précise le type des éléments que le tableau peut contenir
Tableau de nombres
const scores: number[] = [10, 20, 30]
const ids: Array<number> = [1, 2, 3]
Tableau de chaînes
const noms: string[] = ["Alice", "Bob"]
const tags: Array<string> = ["ts", "js"]
// TypeScript bloque les erreurs de type
const notes: number[] = [15, 17]
notes.push("vingt") // âś— Erreur : string n'est pas number
Le typage protège le contenu : impossible d'ajouter le mauvais type !
Deux syntaxes, exactement identiques pour TypeScript
✓ Syntaxe courte — préférée
number[]
string[]
boolean[]
Plus lisible, plus compact, convention TS
Syntaxe générique
Array<number>
Array<string>
Array<boolean>
Plus verbeux — même résultat compilé
Convention : dans le code professionnel, on utilise presque toujours number[] — plus court et tout aussi expressif
Les opérations sur le tableau respectent le type déclaré
const scores: number[] = [10, 20, 30]
// ✓ Opérations valides
scores.push(40)
const total = scores.reduce((a, b) => a + b, 0)
const premier: number = scores[0] // TypeScript sait que c'est un number
// ✗ Opérations invalides
scores.push("bonus") // Erreur : string n'est pas number
const x: string = scores[0] // Erreur : number n'est pas string
push / pop
Éléments validés
Accès par index
Type inféré automatiquement
map / filter
Retour typé aussi
Les Tuples
Taille fixe · Types précis · Idéal pour les retours multiples
Un tableau dont on connaît exactement la taille ET le type de chaque élément
Déclaration d'un tuple
const coordonnees: [number, number] = [48.8, 2.35]
const entree: [string, number] = ["Alice", 30]
const flag: [string, boolean] = ["actif", true]
Accès aux éléments
const user: [string, number] = ["Bob", 25]
const nom: string = user[0] // "Bob"
const age: number = user[1] // 25
// Destructuration
const [n, a] = user
TypeScript connaît le type de chaque position — user[0] est un string, user[1] est un number
Le cas d'usage le plus courant — retourner plusieurs valeurs de types différents
// Fonction qui retourne un tuple
function getUser(id: number): [string, number] {
return ["Alice", 30] // [nom, age]
}
// Utilisation avec destructuration
const [nom, age] = getUser(1)
console.log(`${nom} a ${age} ans`) // "Alice a 30 ans"
// Autre exemple : [succès, message]
function valider(email: string): [boolean, string] {
if (email.includes("@")) return [true, "OK"]
return [false, "Email invalide"]
}
const [ok, msg] = valider("alice@mail.com")
La confusion la plus fréquente avec les tuples
Tableau variable number[]
const notes: number[] = [10, 20]
notes.push(30) // OK
notes.push(40) // OK
Tuple fixe [number, number]
const point: [number, number] = [48, 2]
point.push(3) // Déconseillé !
Règle : number[] = liste de nombres · [number, number] = paire précise comme des coordonnées GPS
Union Types
Le | des types — très courant avec null
Une variable peut avoir l'un ou l'autre des types listés
Syntaxe de base
let valeur: string | number
valeur = "bonjour" // âś“
valeur = 42 // âś“
valeur = true // âś— Erreur
En paramètre de fonction
function afficher(
val: string | number
): void {
console.log(val)
}
afficher("hello") // âś“
afficher(99) // âś“
Le | se lit "ou" : string | number = "une chaîne OU un nombre"
Le pattern standard pour exprimer "une valeur qui peut ne pas exister"
// Chercher un utilisateur — peut ne pas exister
function trouverUtilisateur(id: number): string | null {
const users = ["Alice", "Bob"]
return users[id] ?? null // retourne null si introuvable
}
const resultat = trouverUtilisateur(0)
// TypeScript FORCE à vérifier avant d'utiliser
console.log(resultat.toUpperCase()) // âś— Erreur ! peut ĂŞtre null
if (resultat !== null) {
console.log(resultat.toUpperCase()) // âś“ OK ici
}
string | null oblige à gérer le cas "pas de résultat" — TypeScript vous protège des NPE !
On peut unir non seulement des types, mais des valeurs littérales
// Seulement ces 3 valeurs sont acceptées
type Direction = "gauche" | "droite" | "tout droit"
function deplacer(dir: Direction): void {
console.log(`Je vais ${dir}`)
}
deplacer("gauche") // âś“
deplacer("droite") // âś“
deplacer("en arrière") // ✗ Erreur — valeur non autorisée
Autres exemples courants
"pending" | "success" | "error"
"admin" | "user" | "guest"
1 | 2 | 3 | 4 | 5 // note sur 5
Avantage : autocomplétion dans l'IDE + erreur si valeur invalide — plus robuste qu'un simple string
Type Narrowing
TypeScript suit ta logique dans les if/else
Quand tu vérifie le type dans un if, TypeScript le sait et restreint le type dans la branche
function afficherLongueur(val: string | number): void {
if (typeof val === "string") {
// Ici TypeScript sait que val est un string
console.log(val.length) // âś“ .length existe sur string
console.log(val.toUpperCase()) // âś“
} else {
// Ici TypeScript sait que val est un number
console.log(val.toFixed(2)) // âś“ .toFixed existe sur number
}
}
Le narrowing est automatique : TypeScript analyse le flux du code et réduit le type possible dans chaque branche
MĂŞme principe pour les unions avec null
function saluer(nom: string | null): string {
if (nom === null) {
// Ici : nom est null
return "Bonjour, inconnu !"
}
// Ici : TypeScript sait que nom est string (null exclu)
return `Bonjour, ${nom} !`
}
typeof
Pour les primitifs
=== null
Pour les valeurs nullables
instanceof
Pour les objets (J4+)
Après un if (nom === null) return, TypeScript retire null du type — c'est l'early return pattern
✗ ERREUR — Confondre tableau et tuple
const point: number[] = [10, 20]
const x: number = point[0] // ok mais...
const y: number = point[1] // pas de garantie
point.push(30) // 3 éléments maintenant
✓ CORRECT — Tuple pour coordonnées
const point: [number, number] = [10, 20]
const x: number = point[0] // garanti
const y: number = point[1] // garanti
✗ ERREUR — Utiliser sans narrowing
function f(v: string | number) {
v.toUpperCase() // Erreur !
// number n'a pas toUpperCase
}
✓ CORRECT — Narrowing avant usage
function f(v: string | number) {
if (typeof v === "string") {
v.toUpperCase() // âś“
}
}
Tableaux typés
number[] est la convention préférée — plus courte que Array<number> et protège le contenu
Tuples
[string, number] fixe la taille ET le type de chaque position — idéal pour les coordonnées et retours multiples
Union Types
string | null est le pattern standard pour "résultat ou absence de résultat" — très courant en TypeScript
Type Narrowing
Le narrowing est automatique dans les branches du if — TypeScript suit votre logique
La prochaine étape
J4 — Interfaces, types objets, et type guards avancés