Cours JavaScript et TypeScript · Module 6: Bases de TypeScript
Les type aliases
Dans cette leçon10
Bienvenue de nouveau au laboratoire de génétique de Jurassic Park ! Le Dr Henry Wu va aujourd'hui nous présenter un mécanisme extrêmement utile de TypeScript : les type aliases. Tout comme les scientifiques du parc utilisent des noms raccourcis pour désigner des séquences génétiques complexes, les développeurs utilisent les type aliases pour simplifier des définitions de types complexes.
Qu'est-ce qu'un type alias ?
Un type alias est simplement un nom que l'on donne à un type existant. On peut créer un alias aussi bien pour des types simples que pour des types complexes, ce qui rend le code plus lisible et plus facile à maintenir. C'est un peu comme donner un nom à différents mélanges d'ADN pour pouvoir s'y référer plus facilement pendant le travail en laboratoire.
Syntaxe de base
On définit un type alias à l'aide du mot-clé type :
1// Simple type alias for string
2type SpeciesID = string;
3
4// Using the alias
5const tRexID: SpeciesID = "TREX-01";
6const velociraptorID: SpeciesID = "VELOC-01";Alias pour les types primitifs
On peut appliquer un type alias à des types simples, ce qui peut être utile pour la documentation et pour exprimer clairement l'intention du code :
1// Aliases for simple types
2type SecurityLevel = number;
3type SpeciesName = string;
4type IsPredator = boolean;
5
6// Function using type aliases
7function setEnclosureLevel(species: SpeciesName, predator: IsPredator): SecurityLevel {
8 if (predator) {
9 if (species === "Tyrannosaurus") return 5;
10 if (species === "Velociraptor") return 4;
11 return 3; // Other predators
12 } else {
13 return 2; // Herbivores
14 }
15}
16
17const trexLevel = setEnclosureLevel("Tyrannosaurus", true); // 5
18console.log(`Security level for T-Rex: ${trexLevel}`);Alias pour les types complexes
Les type aliases deviennent particulièrement utiles pour définir des types complexes tels que des objets, des unions ou des tableaux :
1// Alias for object type (similar to interface)
2type Dinosaur = {
3 id: string;
4 name: string;
5 species: string;
6 age: number;
7 weight: number;
8 predator: boolean;
9};
10
11// Alias for union type - different identifiers
12type DinosaurID = string | number;
13
14// Alias for tuple - GPS coordinates with description
15type Location = [number, number, string];
16
17// Alias for array
18type SpeciesList = string[];
19
20// Alias for an object literal with optional fields
21type HealthStatus = {
22 overallHealth: "excellent" | "good" | "average" | "poor" | "critical";
23 temperature?: number;
24 heartRate?: number;
25 treatmentPriority?: 1 | 2 | 3 | 4 | 5;
26 notes?: string;
27};
28
29// Creating objects based on type aliases
30const rexLocation: Location = [35.6895, 139.6917, "T-Rex Enclosure, northern fence"];
31const parkSpecies: SpeciesList = ["Tyrannosaurus", "Velociraptor", "Triceratops", "Brachiosaurus"];
32
33const rexStatus: HealthStatus = {
34 overallHealth: "good",
35 temperature: 38.2,
36 treatmentPriority: 2,
37 notes: "Recently slightly reduced appetite"
38};
39
40// Function working on type alias
41function prepareDinosaurReport(dino: Dinosaur, status: HealthStatus, location: Location): string {
42 const [lat, lng, description] = location;
43
44 return `
45 Dinosaur report:
46 ID: ${dino.id}
47 Name: ${dino.name}
48 Species: ${dino.species}
49 Age: ${dino.age} years
50 Weight: ${dino.weight} kg
51 Predator: ${dino.predator ? "Yes" : "No"}
52
53 Health status: ${status.overallHealth}
54 ${status.temperature ? `Temperature: ${status.temperature}°C` : ""}
55 ${status.heartRate ? `Heart rate: ${status.heartRate} beats/min` : ""}
56
57 Location: ${description} (${lat}, ${lng})
58 `;
59}Alias avec des types generic
Les type aliases peuvent aussi être generic, ce qui nous donne encore plus de flexibilité :
1// Generic type alias for monitoring system data
2type MonitoringData<T> = {
3 measurementTime: Date;
4 value: T;
5 unit: string;
6 valid: boolean;
7};
8
9// Using the generic type alias for different types of measurements
10type TemperatureMeasurement = MonitoringData<number>;
11type ActivityMeasurement = MonitoringData<"low" | "medium" | "high">;
12type StressLevelMeasurement = MonitoringData<1 | 2 | 3 | 4 | 5>;
13
14// Function analyzing monitoring data
15function analyzeData<T>(data: MonitoringData<T>): void {
16 console.log(`Measurement from ${data.measurementTime.toISOString()}`);
17 console.log(`Value: ${data.value} ${data.unit}`);
18 console.log(`Status: ${data.valid ? "Valid" : "Needs attention"}`);
19}
20
21// Sample usage
22const waterTemperature: TemperatureMeasurement = {
23 measurementTime: new Date(),
24 value: 24.5,
25 unit: "°C",
26 valid: true
27};
28
29const trexActivityLevel: ActivityMeasurement = {
30 measurementTime: new Date(),
31 value: "high",
32 unit: "activity level",
33 valid: false // Needs attention because T-Rex is too active
34};
35
36analyzeData(waterTemperature);
37analyzeData(trexActivityLevel);Les type aliases récursifs
Un type alias peut être récursif, ce qui est utile pour modéliser des structures arborescentes comme les hiérarchies d'espèces de dinosaures ou l'organigramme du parc :
1// Recursive type alias for dinosaur category hierarchy
2type DinosaursCategory = {
3 name: string;
4 description?: string;
5 subcategories?: DinosaursCategory[];
6};
7
8// Creating a category hierarchy
9const taxonomy: DinosaursCategory = {
10 name: "Dinosaurs",
11 description: "Main classification of dinosaurs in Jurassic Park",
12 subcategories: [
13 {
14 name: "Theropods",
15 description: "Carnivorous, bipedal dinosaurs",
16 subcategories: [
17 {
18 name: "Tyrannosaurids",
19 subcategories: [
20 { name: "Tyrannosaurus Rex" }
21 ]
22 },
23 {
24 name: "Deinonychosaurs",
25 subcategories: [
26 { name: "Velociraptor" },
27 { name: "Deinonychus" }
28 ]
29 }
30 ]
31 },
32 {
33 name: "Sauropods",
34 description: "Large, four-legged herbivores with long necks",
35 subcategories: [
36 { name: "Brachiosaurus" },
37 { name: "Diplodocus" }
38 ]
39 }
40 ]
41};
42
43// Function to render the taxonomy tree
44function displayTaxonomy(category: DinosaursCategory, level: number = 0): void {
45 const indent = " ".repeat(level);
46 console.log(`${indent}${category.name}`);
47
48 if (category.description) {
49 console.log(`${indent} Description: ${category.description}`);
50 }
51
52 if (category.subcategories && category.subcategories.length > 0) {
53 category.subcategories.forEach(subcategory => {
54 displayTaxonomy(subcategory, level + 1);
55 });
56 }
57}
58
59displayTaxonomy(taxonomy);Type aliases vs interfaces
On compare souvent les type aliases aux interfaces, car dans de nombreux cas ils peuvent être utilisés de manière interchangeable. Il existe cependant quelques différences clés entre eux :
1// Structure definition using interface
2interface DinosaurInterface {
3 id: string;
4 name: string;
5 species: string;
6}
7
8// Equivalent definition using type alias
9type DinosaurType = {
10 id: string;
11 name: string;
12 species: string;
13};
14
15// Both work similarly for basic use
16const dino1: DinosaurInterface = { id: "001", name: "Rex", species: "Tyrannosaurus" };
17const dino2: DinosaurType = { id: "002", name: "Blue", species: "Velociraptor" };Différences clés entre les type aliases et les interfaces
Extensibilité :
- Les interfaces peuvent être étendues en les déclarant plusieurs fois
- Les type aliases ne peuvent pas être « rouverts » : une fois défini, un alias ne peut plus être étendu par la suite
1// Interface can be extended by multiple declarations 2interface AnimalInterface { 3 id: string; 4 species: string; 5} 6 7// Adding new fields to the existing interface 8interface AnimalInterface { 9 age: number; 10 weight: number; 11} 12 13// Now AnimalInterface has all four fields 14const animal: AnimalInterface = { 15 id: "001", 16 species: "Tyrannosaurus", 17 age: 7, 18 weight: 7000 19}; 20 21// A type alias cannot be extended this way 22type AnimalType = { 23 id: string; 24 species: string; 25} 26 27// This would cause an error: Duplicate identifier 'AnimalType' 28// type AnimalType = { 29// age: number; 30// weight: number; 31// }Types complexes :
- Les type aliases peuvent représenter directement des unions, des intersections et d'autres types avancés
- Les interfaces sont davantage centrées sur la définition de la forme des objets
1// Only possible with type aliases 2type SecurityStatus = "normal" | "elevated" | "threat"; 3type GPSCoordinates = [number, number]; 4type AnimalID = string | number; 5 6// With interfaces this would be more cumbersomeLes interfaces pour les classes :
- Les interfaces sont le choix naturel pour définir les contrats que les classes doivent implémenter
- Les type aliases sont plus flexibles pour définir des types complexes
1// Interface for a class 2interface MonitoringSystem { 3 start(): void; 4 stop(): void; 5 getStatus(): string; 6} 7 8// Class implementing the interface 9class EnclosureMonitoring implements MonitoringSystem { 10 start() { console.log("Enclosure monitoring started"); } 11 stop() { console.log("Enclosure monitoring stopped"); } 12 getStatus() { return "Active"; } 13}
Combiner les type aliases avec d'autres fonctionnalités de TypeScript
Les type aliases peuvent être combinés avec d'autres fonctionnalités de TypeScript, ce qui permet de créer des abstractions puissantes :
1// Combining with union types
2type DinosaurData =
3 | { type: "basic"; id: string; species: string }
4 | { type: "extended"; id: string; species: string; age: number; weight: number }
5 | { type: "full"; id: string; species: string; age: number; weight: number; history: string[]; healthStatus: string };
6
7// Function processing different levels of data
8function processDinosaurData(data: DinosaurData): void {
9 console.log(`Processing data for ID: ${data.id}, species: ${data.species}`);
10
11 // We use the discriminated union to determine the data type
12 switch (data.type) {
13 case "basic":
14 console.log("Processing basic data");
15 break;
16 case "extended":
17 console.log(`Age: ${data.age}, Weight: ${data.weight} kg`);
18 break;
19 case "full":
20 console.log(`Age: ${data.age}, Weight: ${data.weight} kg`);
21 console.log(`History: ${data.history.join(", ")}`);
22 console.log(`Health status: ${data.healthStatus}`);
23 break;
24 }
25}
26
27// Usage examples
28const basic: DinosaurData = {
29 type: "basic",
30 id: "TRX-001",
31 species: "Tyrannosaurus"
32};
33
34const extended: DinosaurData = {
35 type: "extended",
36 id: "VEL-001",
37 species: "Velociraptor",
38 age: 4,
39 weight: 150
40};
41
42const full: DinosaurData = {
43 type: "full",
44 id: "TRI-001",
45 species: "Triceratops",
46 age: 10,
47 weight: 8000,
48 history: ["Born: 2013", "Transfer from Location B: 2016", "Broken horns: 2018", "Recovery: 2019"],
49 healthStatus: "Good"
50};
51
52processDinosaurData(basic);
53processDinosaurData(extended);
54processDinosaurData(full);Combiner les types utilitaires avec les type aliases
TypeScript propose des types utilitaires intégrés que l'on peut combiner avec les type aliases, ce qui nous donne encore plus de possibilités pour modéliser nos données :
1// Base interface for a dinosaur
2interface Dinosaur {
3 id: string;
4 name: string;
5 species: string;
6 age: number;
7 weight: number;
8 gender: "male" | "female";
9 predator: boolean;
10 nocturnal: boolean;
11 healthStatus: "excellent" | "good" | "needs attention" | "sick" | "critical";
12}
13
14// Type aliases using utility types
15
16// Read-only type - useful for data that should not be modified
17type DinosaurReadOnly = Readonly<Dinosaur>;
18
19// Type with selected fields - useful for partial data
20type DinosaurBasic = Pick<Dinosaur, "id" | "name" | "species">;
21
22// Type with omitted fields - useful when we want to exclude certain data
23type DinosaurWithoutStatus = Omit<Dinosaur, "healthStatus">;
24
25// Type with optional fields - useful for partial updates
26type DinosaurPartial = Partial<Dinosaur>;
27
28// Type with required fields - forcing all fields to be defined
29type DinosaurRequired = Required<Dinosaur>;
30
31// Record type - useful for key-indexed collections
32type DinosaursDatabase = Record<string, Dinosaur>;
33
34// Usage examples
35const rexReadOnly: DinosaurReadOnly = {
36 id: "TRX-001",
37 name: "Rex",
38 species: "Tyrannosaurus",
39 age: 7,
40 weight: 7000,
41 gender: "female",
42 predator: true,
43 nocturnal: false,
44 healthStatus: "good"
45};
46
47// rexReadOnly.age = 8; // Error: Cannot assign to 'age' because it is a read-only property
48
49const rexBasic: DinosaurBasic = {
50 id: "TRX-001",
51 name: "Rex",
52 species: "Tyrannosaurus"
53};
54
55// Partial data update
56function updateDinosaurData(id: string, data: DinosaurPartial): void {
57 console.log(`Updating data for dinosaur ${id}`);
58 console.log(data);
59 // In a real application we would update the data in the database
60}
61
62updateDinosaurData("TRX-001", {
63 age: 8,
64 weight: 7200,
65 healthStatus: "needs attention"
66});
67
68// Dinosaur database
69const database: DinosaursDatabase = {
70 "TRX-001": {
71 id: "TRX-001",
72 name: "Rex",
73 species: "Tyrannosaurus",
74 age: 7,
75 weight: 7000,
76 gender: "female",
77 predator: true,
78 nocturnal: false,
79 healthStatus: "good"
80 },
81 "VEL-001": {
82 id: "VEL-001",
83 name: "Blue",
84 species: "Velociraptor",
85 age: 4,
86 weight: 150,
87 gender: "female",
88 predator: true,
89 nocturnal: true,
90 healthStatus: "excellent"
91 }
92};
93
94console.log(`Number of dinosaurs in the database: ${Object.keys(database).length}`);Exemple pratique : le modèle de données de Jurassic Park
Voyons maintenant comment utiliser les type aliases avec d'autres fonctionnalités de TypeScript pour créer un modèle de données complet pour le système de gestion de Jurassic Park :
1// Base types
2type ID = string;
3type Coordinates = [number, number];
4type AccessLevel = 1 | 2 | 3 | 4 | 5;
5type ActivityStatus = "active" | "inactive" | "under maintenance";
6type HealthStatus = "excellent" | "good" | "needs attention" | "sick" | "critical";
7
8// Dinosaur types
9type TaxonomicGroup = "theropods" | "sauropods" | "ceratopsians" | "stegosaurs" | "ankylosaurs";
10
11type DietClass = "herbivore" | "carnivore" | "omnivore";
12
13type SpeciesData = {
14 name: string;
15 taxonomicGroup: TaxonomicGroup;
16 diet: DietClass;
17 geologicalEra: string;
18 averageWeight: number;
19 averageLength: number;
20 averageAge: number;
21 threat: AccessLevel;
22 description: string;
23};
24
25type Specimen = {
26 id: ID;
27 species: string;
28 firstName: string;
29 age: number;
30 weight: number;
31 gender: "male" | "female";
32 status: HealthStatus;
33 location: ID;
34 arrivalDate: Date;
35 history: MedicalHistory[];
36};
37
38type MedicalHistory = {
39 date: Date;
40 type: "examination" | "treatment" | "vaccination" | "surgery";
41 description: string;
42 veterinarian: ID;
43};
44
45// Employee types
46type Position =
47 | "director"
48 | "researcher"
49 | "veterinarian"
50 | "trainer"
51 | "security"
52 | "maintenance"
53 | "technician"
54 | "guide";
55
56type Employee = {
57 id: ID;
58 firstName: string;
59 lastName: string;
60 position: Position;
61 accessLevel: AccessLevel;
62 hireDate: Date;
63 contact: {
64 phone: string;
65 email: string;
66 address?: string;
67 };
68 specializationAreas?: string[];
69};
70
71// Location types
72type LocationType =
73 | "enclosure"
74 | "laboratory"
75 | "operations center"
76 | "public zone"
77 | "dining"
78 | "shop"
79 | "attraction";
80
81type SecuritySystems = {
82 fence: boolean;
83 videoMonitoring: boolean;
84 motionSensors: boolean;
85 backupPower: boolean;
86 electricVoltage?: number; // only for predator enclosures
87};
88
89type Location = {
90 id: ID;
91 name: string;
92 type: LocationType;
93 coordinates: Coordinates;
94 area: number; // in hectares
95 capacity: number; // maximum number of people/specimens
96 requiredAccessLevel: AccessLevel;
97 status: ActivityStatus;
98 securitySystems: SecuritySystems;
99};
100
101// Event types
102type EventType =
103 | "dinosaurEscape"
104 | "systemFailure"
105 | "accident"
106 | "illness"
107 | "birth"
108 | "death"
109 | "specimenTransfer"
110 | "weatherThreat";
111
112type Event = {
113 id: ID;
114 type: EventType;
115 date: Date;
116 location: ID;
117 dinosaurParticipants?: ID[];
118 employeeParticipants?: ID[];
119 description: string;
120 status: "in progress" | "resolved" | "closed";
121 priority: 1 | 2 | 3 | 4 | 5;
122 preventiveActions?: string[];
123};
124
125// Park management system
126type ManagementSystem = {
127 dinosaurs: Record<ID, Specimen>;
128 species: Record<string, SpeciesData>;
129 employees: Record<ID, Employee>;
130 locations: Record<ID, Location>;
131 events: Record<ID, Event>;
132
133 // System methods
134 addSpecimen: (specimen: Omit<Specimen, "id">) => ID;
135 updateSpecimenStatus: (id: ID, status: HealthStatus) => void;
136 moveSpecimen: (id: ID, newLocation: ID) => boolean;
137 findSpecimens: (filters: Partial<Specimen>) => Specimen[];
138 generateStatusReport: () => StatusReport;
139};
140
141type StatusReport = {
142 specimenCount: number;
143 speciesDistribution: Record<string, number>;
144 healthStatuses: Record<HealthStatus, number>;
145 locationOccupancy: Record<ID, { capacity: number; current: number }>;
146 recentEvents: Event[];
147 alerts: string[];
148};
149
150// Simulating part of the system
151const jurassicParkSystem: Partial<ManagementSystem> = {
152 dinosaurs: {},
153 species: {
154 "Tyrannosaurus": {
155 name: "Tyrannosaurus Rex",
156 taxonomicGroup: "theropods",
157 diet: "carnivore",
158 geologicalEra: "late Cretaceous",
159 averageWeight: 7000,
160 averageLength: 12,
161 averageAge: 30,
162 threat: 5,
163 description: "One of the largest predators that ever walked the Earth."
164 },
165 "Velociraptor": {
166 name: "Velociraptor",
167 taxonomicGroup: "theropods",
168 diet: "carnivore",
169 geologicalEra: "late Cretaceous",
170 averageWeight: 15,
171 averageLength: 1.8,
172 averageAge: 25,
173 threat: 4,
174 description: "Small, fast and intelligent predator, hunting in packs."
175 }
176 },
177 locations: {
178 "LOC-001": {
179 id: "LOC-001",
180 name: "T-Rex Paddock",
181 type: "enclosure",
182 coordinates: [20.1234, -75.8765],
183 area: 8,
184 capacity: 2,
185 requiredAccessLevel: 4,
186 status: "active",
187 securitySystems: {
188 fence: true,
189 videoMonitoring: true,
190 motionSensors: true,
191 backupPower: true,
192 electricVoltage: 10000
193 }
194 }
195 }
196};
197
198// Function demonstrating usage of the types
199function demonstrateManagementSystem() {
200 console.log("Jurassic Park Management System");
201 console.log("----------------------------------");
202
203 console.log("Available species:");
204 Object.values(jurassicParkSystem.species || {}).forEach(species => {
205 console.log(`- ${species.name} (${species.diet}, threat: ${species.threat})`);
206 });
207
208 console.log("\nAvailable locations:");
209 Object.values(jurassicParkSystem.locations || {}).forEach(loc => {
210 console.log(`- ${loc.name} (type: ${loc.type}, status: ${loc.status}, access: level ${loc.requiredAccessLevel})`);
211 });
212}
213
214demonstrateManagementSystem();Résumé
Les type aliases en TypeScript sont un mécanisme puissant qui permet d'écrire un code plus lisible, plus facile à maintenir et plus sûr. Dans le contexte de la gestion d'un système aussi complexe que Jurassic Park, les type aliases nous permettent de modéliser précisément les données et les relations qui existent entre elles.
| Fonctionnalité du type alias | Utilisation à Jurassic Park |
|---|---|
| Alias de base | Types d'identifiants, niveaux de sécurité |
| Type aliases complexes | Structures de données pour les dinosaures, les employés, les emplacements |
| Alias generic | Système de surveillance pour différents paramètres |
| Types récursifs | Hiérarchies d'espèces, organigramme |
| Unions discriminées | Différents niveaux de données, types d'événements |
| Types utilitaires | Gestion de la mutabilité et de l'accessibilité des données |
Le Dr Wu résume ainsi : « Les type aliases sont comme nos check-lists et nos protocoles de laboratoire : ils nous permettent de définir clairement à quoi doivent ressembler les données et les opérations, tout en rendant l'ensemble du système plus compréhensible. Dans un projet aussi complexe que Jurassic Park, où la moindre erreur peut avoir des conséquences catastrophiques, des outils aussi précis n'ont pas de prix. »
Code de cette leçon : index.ts
1// Type Aliases dans le Parc Jurassique
2console.log("Type Aliases TypeScript\n");
3
4// ===========================================
5// 1. Type aliases de base
6// ===========================================
7console.log("=== TYPE ALIASES DE BASE ===");
8
9// Alias for simple types
10type DinosaurID = string | number;
11type Weight = number;
12type Species = string;
13
14let id1: DinosaurID = "DINO-001";
15let id2: DinosaurID = 123;
16let weight: Weight = 8000;
17let species: Species = "Tyrannosaurus Rex";
18
19console.log("ID:", id1, id2);
20console.log("Weight:", weight);
21console.log("Species:", species);
22
23// ===========================================
24// 2. Type vs Interface
25// ===========================================
26console.log("\n=== TYPE VS INTERFACE ===");
27
28// Type alias
29type DinosaurType = {
30 name: string;
31 species: string;
32 age: number;
33};
34
35// Interface
36interface DinosaurInterface {
37 name: string;
38 species: string;
39 age: number;
40}
41
42const dino1: DinosaurType = {
43 name: "Rex",
44 species: "T-Rex",
45 age: 5
46};
47
48const dino2: DinosaurInterface = {
49 name: "Blue",
50 species: "Velociraptor",
51 age: 3
52};
53
54console.log("Type:", dino1);
55console.log("Interface:", dino2);
56
57// ===========================================
58// 3. Union types avec des aliases
59// ===========================================
60console.log("\n=== UNION TYPES ===");
61
62type Diet = "carnivore" | "herbivore" | "omnivore";
63type Period = "Triassic" | "Jurassic" | "Cretaceous";
64type SecurityLevel = "low" | "medium" | "high" | "critical";
65
66type Dinosaur = {
67 name: string;
68 diet: Diet;
69 period: Period;
70 dangerLevel: SecurityLevel;
71};
72
73const trex: Dinosaur = {
74 name: "Tyrannosaurus Rex",
75 diet: "carnivore",
76 period: "Cretaceous",
77 dangerLevel: "critical"
78};
79
80console.log("T-Rex:", trex);
81
82// ===========================================
83// 4. Intersection types avec des aliases
84// ===========================================
85console.log("\n=== INTERSECTION TYPES ===");
86
87type HasName = {
88 name: string;
89};
90
91type HasWeight = {
92 weight: number;
93};
94
95type HasDiet = {
96 diet: Diet;
97};
98
99// Combining types
100type CompleteDinosaur = HasName & HasWeight & HasDiet & {
101 species: string;
102};
103
104const velociraptor: CompleteDinosaur = {
105 name: "Blue",
106 weight: 350,
107 diet: "carnivore",
108 species: "Velociraptor"
109};
110
111console.log("Complete dinosaur:", velociraptor);
112
113// ===========================================
114// 5. Function types
115// ===========================================
116console.log("\n=== FUNCTION TYPES ===");
117
118// Type function
119type DinosaurFilter = (dino: Dinosaur) => boolean;
120type DinosaurTransformer = (dino: Dinosaur) => string;
121type DinosaurComparator = (a: Dinosaur, b: Dinosaur) => number;
122
123const carnivoreFilter: DinosaurFilter = (dino) => dino.diet === "carnivore";
124const nameTransformer: DinosaurTransformer = (dino) => `${dino.name}`;
125const dangerComparator: DinosaurComparator = (a, b) => {
126 const levels = { low: 1, medium: 2, high: 3, critical: 4 };
127 return levels[b.dangerLevel] - levels[a.dangerLevel];
128};
129
130console.log("Is carnivore:", carnivoreFilter(trex));
131console.log("Transformed:", nameTransformer(trex));
132
133// ===========================================
134// 6. Tuple types
135// ===========================================
136console.log("\n=== TUPLE TYPES ===");
137
138type Coordinates = [latitude: number, longitude: number];
139type DinosaurData = [name: string, weight: number, isCarnivore: boolean];
140type RGB = [red: number, green: number, blue: number];
141
142const paddockLocation: Coordinates = [22.3964, -159.5261];
143const dinoInfo: DinosaurData = ["Rexy", 8000, true];
144const warningColor: RGB = [255, 0, 0];
145
146console.log("Location:", paddockLocation);
147console.log("Dino info:", dinoInfo);
148console.log("Warning color:", warningColor);
149
150// ===========================================
151// 7. Mapped types avec des aliases
152// ===========================================
153console.log("\n=== MAPPED TYPES ===");
154
155type DinosaurStats = {
156 health: number;
157 hunger: number;
158 energy: number;
159 happiness: number;
160};
161
162// All fields comme readonly
163type ReadonlyStats = {
164 readonly [K in keyof DinosaurStats]: DinosaurStats[K];
165};
166
167// All fields comme optionnels
168type PartialStats = {
169 [K in keyof DinosaurStats]?: DinosaurStats[K];
170};
171
172const stats: DinosaurStats = {
173 health: 100,
174 hunger: 50,
175 energy: 80,
176 happiness: 90
177};
178
179const readonlyStats: ReadonlyStats = stats;
180// readonlyStats.health = 90; // Error
181
182const partialStats: PartialStats = {
183 health: 100,
184 energy: 80
185 // remaining fields optional
186};
187
188console.log("Stats:", stats);
189console.log("Partial stats:", partialStats);
190
191// ===========================================
192// 8. Conditional types
193// ===========================================
194console.log("\n=== CONDITIONAL TYPES ===");
195
196// Conditional type
197type IsCarnivore<T> = T extends { diet: "carnivore" } ? true : false;
198
199type TRexIsCarnivore = IsCarnivore<typeof trex>; // true
200type VelociraptorIsCarnivore = IsCarnivore<typeof velociraptor>; // true
201
202// Extract - extracts types satisfying condition
203type DinosaurSize = "small" | "medium" | "large" | "extra-large";
204type LargeSizes = Extract<DinosaurSize, "large" | "extra-large">;
205
206// Exclude - removes types satisfying condition
207type SmallMediumSizes = Exclude<DinosaurSize, "large" | "extra-large">;
208
209console.log("Conditional types defined");
210
211// ===========================================
212// 9. Utility types z aliases
213// ===========================================
214console.log("\n=== UTILITY TYPES ===");
215
216type BaseDinosaur = {
217 id: string;
218 name: string;
219 species: string;
220 weight: number;
221};
222
223// Partial - tous les fields optionnels
224type PartialDinosaur = Partial<BaseDinosaur>;
225
226// Required - tous les fields obligatoires
227type RequiredDinosaur = Required<BaseDinosaur>;
228
229// Pick - select specific fields
230type DinosaurSummary = Pick<BaseDinosaur, "name" | "species">;
231
232// Omit - remove specific fields
233type PublicDinosaur = Omit<BaseDinosaur, "id">;
234
235// Record - mapping des clés vers un type
236type DinosaurCollection = Record<string, BaseDinosaur>;
237
238const partialDino: PartialDinosaur = {
239 name: "Rex"
240 // tous les autres fields optionnels
241};
242
243const summary: DinosaurSummary = {
244 name: "Rexy",
245 species: "T-Rex"
246};
247
248const collection: DinosaurCollection = {
249 "t-rex": {
250 id: "001",
251 name: "Rexy",
252 species: "T-Rex",
253 weight: 8000
254 },
255 "velociraptor": {
256 id: "002",
257 name: "Blue",
258 species: "Velociraptor",
259 weight: 350
260 }
261};
262
263console.log("Partial:", partialDino);
264console.log("Summary:", summary);
265console.log("Collection:", collection);
266
267// ===========================================
268// 10. Résumé
269// ===========================================
270console.log("\n=== RÉSUMÉ ===");
271console.log("Type Aliases - names for types");
272console.log("Union & Intersection - combining types");
273console.log("Function Types - types de function");
274console.log("Tuple Types - tuples");
275console.log("Mapped Types - type transformation");
276console.log("Conditional Types - types conditionnels");
277console.log("Utility Types - built-in tools");
278
279console.log("\nType Aliases maîtrisés !");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. Qu’est-ce qu’un alias de type en TypeScript ?
2. Qu’est-ce qu’une garde de type (type guard) en TypeScript ?
Voici 2 des 3 questions de cette leçon. Réponds aux autres dans le jeu.
Tâches pratiques dans le jeu
- Éditeur de code
Crée un alias de type DinoStatus et une fonction avec une garde de type qui vérifie si un dinosaure est carnivore.
- Clique dans l'ordre
Ordonne les éléments d’une assertion de type en TypeScript :
- Tri vertical
Ordonne les méthodes de vérification de type en TypeScript de la plus simple à la plus avancée :