Welcome back to the Jurassic Park genetics laboratory! Dr. Henry Wu will today introduce us to an extremely useful TypeScript mechanism - type aliases. Just as scientists in the park use shorthand names for complex genetic sequences, programmers use type aliases to simplify complex type definitions.
A type alias is simply a name we give to an existing type. We can alias both simple and complex types, which makes code more readable and easier to maintain. It's like naming different DNA mixtures so they're easier to refer to during lab work.
We define type aliases using the
type keyword:1// Simple type alias for string
2type SpeciesID = string;
3
4// Using the alias
5const tRexID: SpeciesID = "TREX-01";
6const velociraptorID: SpeciesID = "VELOC-01";Type aliases can be applied to simple types, which can be helpful for documentation and code intent:
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}`);Type aliases become especially useful when defining complex types such as objects, unions or arrays:
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}Type aliases can also be generic, giving us even greater flexibility:
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);Type aliases can be recursive, which is useful for modeling tree structures such as dinosaur species hierarchies or park organizational structures:
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 are often compared to interfaces because in many cases they can be used interchangeably. However, there are some key differences between them:
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" };Extensibility:
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 wiek: number;
10 waga: number;
11}
12
13// Now AnimalInterface has all four fields
14const animal: AnimalInterface = {
15 id: "001",
16 species: "Tyrannosaurus",
17 wiek: 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// }Complex types:
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 cumbersomeInterfaces for classes:
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}Type aliases can be combined with other TypeScript features, creating powerful abstractions:
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);TypeScript offers built-in utility types that can be combined with type aliases, giving us even greater data modeling capabilities:
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}`);Let's now see how we can use type aliases together with other TypeScript features to create a comprehensive data model for the Jurassic Park management system:
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();Type aliases in TypeScript are a powerful mechanism that allows the creation of more readable, maintainable and safe code. In the context of managing a complex system like Jurassic Park, type aliases allow us to accurately model data and the relationships between them.
| Type alias feature | Use in Jurassic Park | |-------------------|----------------------| | Basic aliases | Types of identifiers, security levels | | Complex type aliases | Data structures for dinosaurs, employees, locations | | Generic aliases | Monitoring system for different parameters | | Recursive types | Species hierarchies, organizational structure | | Discriminated unions | Different data levels, types of events | | Utility types | Managing data mutability and accessibility |
Dr. Wu summarizes: "Type aliases are like our checklists and protocols in the laboratory - they allow us to clearly define what data and operations should look like, while making the whole system more understandable. In a project as complex as Jurassic Park, where the smallest error can lead to catastrophic consequences, such precise tools are invaluable."