JavaScript and TypeScript course Β· Module 6: TypeScript Basics
Interface definitions
In this lesson11
Welcome back to Jurassic Park! Today, under the watchful eye of Dr. Henry Wu, we will explore a fundamental concept of TypeScript that is just as crucial for code organization as security protocols are for the park's proper operation - interfaces.
What are interfaces in TypeScript?
Interfaces in TypeScript define contracts in code and describe the structure of objects. They are like detailed protocols that specify what a given object should contain. In the context of Jurassic Park, interfaces can be compared to safety standards and handling protocols for different dinosaur species - each species has its own specific requirements and traits.
Basic interface syntax
We define an interface using the interface keyword:
1interface Dinosaur {
2 id: number;
3 name: string;
4 species: string;
5 age: number;
6 weight: number;
7}
8
9// We create an object that must satisfy the interface requirements
10const rex: Dinosaur = {
11 id: 1,
12 name: "Rex",
13 species: "Tyrannosaurus",
14 age: 7,
15 weight: 8000
16};
17
18// The following code would cause an error because required properties are missing
19// const raptor: Dinosaur = {
20// id: 2,
21// name: "Blue"
22// };Optional properties
Some properties in an interface can be optional, marked by adding a question mark (?). It's like marking optional handling procedures for individual dinosaurs.
1interface DinosaurSpecimen {
2 id: number;
3 name: string;
4 species: string;
5 rfidTag?: string; // Optional RFID tag
6 lastExamination?: Date; // Optional date of last examination
7 notes?: string; // Optional research notes
8}
9
10// Object satisfying the interface, but without all optional properties
11const specimen1: DinosaurSpecimen = {
12 id: 101,
13 name: "Specimen A",
14 species: "Velociraptor"
15};
16
17// Object with some optional properties
18const specimen2: DinosaurSpecimen = {
19 id: 102,
20 name: "Specimen B",
21 species: "Dilophosaurus",
22 rfidTag: "DILO-102",
23 notes: "Shows aggressive behavior in the presence of new objects"
24};Read-only (readonly)
Some properties should only be modified when the object is created. In TypeScript we can achieve this using the readonly modifier. It's like safety procedures that, once established, cannot be changed during normal operations.
1interface GeneticCode {
2 readonly id: string;
3 readonly sequence: string;
4 readonly donorSpecies: string;
5 modifications: string[];
6 isolationDate: Date;
7}
8
9// Creating genetic code
10const trexCode: GeneticCode = {
11 id: "GEN-TREX-001",
12 sequence: "ACGTTGCAAGCTA...",
13 donorSpecies: "West African frog",
14 modifications: ["Gap DNA filling", "Aggression gene correction"],
15 isolationDate: new Date("2022-05-15")
16};
17
18// We can add new modifications
19trexCode.modifications.push("Immune resistance enhancement");
20
21// But we cannot change the values of readonly fields
22// trexCode.id = "GEN-TREX-002"; // Error: Cannot assign to 'id' because it is a read-only property
23// trexCode.sequence = "GCTA..."; // Error: Cannot assign to 'sequence' because it is a read-only propertyFunction interfaces
Interfaces can also define function types, which is useful when describing callbacks or functions passed as parameters. In the context of the park, it's like defining standard procedures for handling different situations.
1// Security check function interface
2interface SecurityCheck {
3 (threatLevel: number, parkZone: string): boolean;
4}
5
6// Implementation of a function conforming to the interface
7const checkAccess: SecurityCheck = function(level, zone) {
8 // Access checking logic
9 if (zone === "T-Rex Enclosure" && level < 5) {
10 return false; // Deny access to T-Rex zone for staff below level 5
11 }
12
13 if (zone.includes("Laboratory") && level < 4) {
14 return false; // Deny access to laboratories for staff below level 4
15 }
16
17 return true; // Access permitted for other cases
18};
19
20// Using the function
21console.log(checkAccess(3, "T-Rex Enclosure")); // false
22console.log(checkAccess(5, "T-Rex Enclosure")); // true
23console.log(checkAccess(3, "Public area")); // trueIndexable types
Interfaces can define indexable types - useful when we have objects with a dynamic number of properties of the same type. In the context of the park, this could be a dinosaur database indexed by their identifiers.
1// Interface for a dinosaur database
2interface DinosaursDatabase {
3 [id: string]: {
4 name: string;
5 species: string;
6 age: number;
7 health: "good" | "needs attention" | "critical";
8 };
9}
10
11// Creating the database
12const database: DinosaursDatabase = {
13 "TREX-001": {
14 name: "Rex",
15 species: "Tyrannosaurus",
16 age: 7,
17 health: "good"
18 },
19 "VELOC-001": {
20 name: "Blue",
21 species: "Velociraptor",
22 age: 4,
23 health: "good"
24 },
25 "TRIC-003": {
26 name: "Trike",
27 species: "Triceratops",
28 age: 10,
29 health: "needs attention"
30 }
31};
32
33// Accessing data
34console.log(database["VELOC-001"].name); // "Blue"
35
36// Adding a new entry
37database["STEGO-002"] = {
38 name: "Spike",
39 species: "Stegosaurus",
40 age: 6,
41 health: "good"
42};Class interfaces
Interfaces can also define contracts that classes must implement. It's like operational standards that every department in the park must meet.
1// Interface for security systems
2interface SecuritySystem {
3 name: string;
4 isActive: boolean;
5 securityLevel: number;
6
7 activate(): void;
8 deactivate(): void;
9 checkStatus(): string;
10}
11
12// Class implementing the interface
13class ElectronicFenceSystem implements SecuritySystem {
14 name: string;
15 isActive: boolean;
16 securityLevel: number;
17 voltage: number; // Additional property specific to this class
18
19 constructor(name: string, securityLevel: number, voltage: number) {
20 this.name = name;
21 this.isActive = false; // Initially inactive
22 this.securityLevel = securityLevel;
23 this.voltage = voltage;
24 }
25
26 activate(): void {
27 this.isActive = true;
28 console.log(`System ${this.name} activated. Voltage: ${this.voltage}V`);
29 }
30
31 deactivate(): void {
32 this.isActive = false;
33 console.log(`System ${this.name} deactivated.`);
34 }
35
36 checkStatus(): string {
37 return this.isActive
38 ? `${this.name}: ACTIVE (Level ${this.securityLevel})`
39 : `${this.name}: INACTIVE`;
40 }
41
42 // Method specific to this class
43 increaseVoltage(by: number): void {
44 this.voltage += by;
45 console.log(`Voltage increased to ${this.voltage}V`);
46 }
47}
48
49// Using the class
50const trexFence = new ElectronicFenceSystem("T-Rex Fence", 5, 10000);
51trexFence.activate();
52console.log(trexFence.checkStatus());
53trexFence.increaseVoltage(2000);Extending interfaces
Interfaces can extend other interfaces, similar to how in biology species share common traits but also have their own unique properties.
1// Basic interface for all animals in the park
2interface Animal {
3 id: number;
4 species: string;
5 age: number;
6 weight: number;
7}
8
9// Interface for dinosaurs extending the Animal interface
10interface Dinosaur extends Animal {
11 era: string; // e.g. "Cretaceous", "Jurassic"
12 isPredator: boolean;
13 mainDiet: string[];
14}
15
16// Interface for predatory dinosaurs extending the Dinosaur interface
17interface PredatoryDinosaur extends Dinosaur {
18 biteForce: number; // in PSI
19 runSpeed: number; // in km/h
20 huntingBehavior: string[];
21}
22
23// Creating an object conforming to the PredatoryDinosaur interface
24const velociraptor: PredatoryDinosaur = {
25 id: 101,
26 species: "Velociraptor",
27 age: 4,
28 weight: 70,
29 era: "Cretaceous",
30 isPredator: true,
31 mainDiet: ["small mammals", "lizards", "other small dinosaurs"],
32 biteForce: 1000,
33 runSpeed: 60,
34 huntingBehavior: ["pack hunting", "ambush", "chase"]
35};Declaration merging for interfaces
In TypeScript it is possible to define the same interface multiple times - the declarations will be merged. This is useful when we want to add new properties to an existing interface.
1// Initial definition of the security protocol
2interface SecurityProtocol {
3 name: string;
4 threatLevel: number;
5 evacuationProcedure: string;
6}
7
8// Extending the protocol with additional properties
9interface SecurityProtocol {
10 responsibleStaff: string[];
11 responseTime: number; // in minutes
12}
13
14// The object must contain all properties from both declarations
15const alphaProtocol: SecurityProtocol = {
16 name: "Protocol Alpha",
17 threatLevel: 3,
18 evacuationProcedure: "Evacuation towards the main control center",
19 responsibleStaff: ["Dr. Wu", "Owen Grady", "Claire Dearing"],
20 responseTime: 15
21};Interfaces vs types
TypeScript also offers the type keyword for defining types. Although in many cases interfaces and types can be used interchangeably, there are differences between them:
1// Definition using interface
2interface EvacuationPlan {
3 route: string[];
4 estimatedTime: number;
5 assemblyPoints: string[];
6}
7
8// Equivalent definition using type
9type EvacuationPlanType = {
10 route: string[];
11 estimatedTime: number;
12 assemblyPoints: string[];
13};
14
15// Both work similarly for basic use
16const planA: EvacuationPlan = {
17 route: ["Operations center", "Main Street", "Evacuation hall"],
18 estimatedTime: 25,
19 assemblyPoints: ["Operations center", "Evacuation hall"]
20};
21
22const planB: EvacuationPlanType = {
23 route: ["Gallimimus Enclosure", "Innovation Center", "Evacuation hall"],
24 estimatedTime: 30,
25 assemblyPoints: ["Innovation Center", "Evacuation hall"]
26};Key differences between interface and type:
Extensibility:
- Interfaces can be extended by multiple declarations with the same name
- Types cannot be "opened" - once declared, a type cannot be extended
Complex types:
- Types can directly represent primitive types, unions, intersections
- Interfaces are more focused on defining the shape of objects
1// Only possible with types
2type DinosaurID = string | number;
3type EnclosureCoordinates = [number, number, string]; // Tuple
4type DinosaurStatus = "active" | "resting" | "sleeping"; // Union of literals
5
6// More natural with interfaces
7interface Procedure {
8 name: string;
9 steps: string[];
10 executionTime: number;
11 responsibleStaff: string[];
12}Practical application of interfaces
Let's look at how we can use interfaces to model the Jurassic Park management system:
1// Basic interfaces
2interface ParkPerson {
3 id: string;
4 firstName: string;
5 lastName: string;
6 accessLevel: 1 | 2 | 3 | 4 | 5;
7 hireDate: Date;
8}
9
10interface Location {
11 id: string;
12 name: string;
13 type: "enclosure" | "laboratory" | "operations center" | "public zone";
14 coordinates: [number, number]; // [latitude, longitude]
15 requiredAccessLevel: 1 | 2 | 3 | 4 | 5;
16}
17
18interface DinosaurSpecies {
19 name: string;
20 geologicalEra: string;
21 type: "herbivore" | "predator" | "omnivore";
22 averageWeight: number;
23 averageAge: number;
24 dangerLevel: 1 | 2 | 3 | 4 | 5;
25 dietRequirements: string[];
26 habitatRequirements: string[];
27}
28
29interface DinosaurSpecimen {
30 id: string;
31 species: string;
32 firstName?: string;
33 age: number;
34 weight: number;
35 gender: "male" | "female";
36 location: string; // Location ID
37 healthStatus: "excellent" | "good" | "needs attention" | "sick" | "critical";
38 lastExamination: Date;
39 rfidTag: string;
40 notes?: string;
41}
42
43// Interfaces for management systems
44interface SpecimenTrackingSystem {
45 getPosition(specimenId: string): [number, number];
46 trackMovement(specimenId: string, trackingTime: number): [number, number][];
47 checkIfInZone(specimenId: string, zoneId: string): boolean;
48 alertWhenOutsideZone(specimenId: string, callback: (specimen: DinosaurSpecimen) => void): void;
49}
50
51interface EmployeeManagementSystem {
52 addEmployee(employee: ParkPerson): void;
53 removeEmployee(id: string): boolean;
54 grantAccess(employeeId: string, level: 1 | 2 | 3 | 4 | 5): boolean;
55 checkPresenceInZone(employeeId: string, zoneId: string): boolean;
56}
57
58// Example implementation
59class ParkManagementSystem {
60 private employees: ParkPerson[] = [];
61 private locations: Location[] = [];
62 private species: DinosaurSpecies[] = [];
63 private specimens: DinosaurSpecimen[] = [];
64
65 // Methods for staff
66 addEmployee(employee: ParkPerson): void {
67 this.employees.push(employee);
68 console.log(`Added employee: ${employee.firstName} ${employee.lastName}`);
69 }
70
71 // Methods for locations
72 addLocation(location: Location): void {
73 this.locations.push(location);
74 console.log(`Added location: ${location.name}`);
75 }
76
77 // Methods for species
78 addSpecies(species: DinosaurSpecies): void {
79 this.species.push(species);
80 console.log(`Added species: ${species.name}`);
81 }
82
83 // Methods for specimens
84 addSpecimen(specimen: DinosaurSpecimen): void {
85 this.specimens.push(specimen);
86 console.log(`Added specimen: ${specimen.id} (${specimen.species})`);
87 }
88
89 // Management methods
90 checkAccess(employeeId: string, locationId: string): boolean {
91 const employee = this.employees.find(p => p.id === employeeId);
92 const location = this.locations.find(l => l.id === locationId);
93
94 if (!employee || !location) return false;
95
96 return employee.accessLevel >= location.requiredAccessLevel;
97 }
98
99 findSpecimensBySpecies(speciesName: string): DinosaurSpecimen[] {
100 return this.specimens.filter(o => o.species === speciesName);
101 }
102
103 findSpecimensInZone(zoneId: string): DinosaurSpecimen[] {
104 return this.specimens.filter(o => o.location === zoneId);
105 }
106
107 generateParkStatusReport(): {
108 employeeCount: number;
109 locationCount: number;
110 speciesCount: number;
111 specimenCount: number;
112 specimenHealthStatus: {
113 excellent: number;
114 good: number;
115 needsAttention: number;
116 sick: number;
117 critical: number;
118 }
119 } {
120 // Analyzing health status of all specimens
121 const healthStatus = {
122 excellent: 0,
123 good: 0,
124 needsAttention: 0,
125 sick: 0,
126 critical: 0
127 };
128
129 this.specimens.forEach(specimen => {
130 if (specimen.healthStatus === "excellent") healthStatus.excellent++;
131 else if (specimen.healthStatus === "good") healthStatus.good++;
132 else if (specimen.healthStatus === "needs attention") healthStatus.needsAttention++;
133 else if (specimen.healthStatus === "sick") healthStatus.sick++;
134 else if (specimen.healthStatus === "critical") healthStatus.critical++;
135 });
136
137 return {
138 employeeCount: this.employees.length,
139 locationCount: this.locations.length,
140 speciesCount: this.species.length,
141 specimenCount: this.specimens.length,
142 specimenHealthStatus: healthStatus
143 };
144 }
145}
146
147// Example usage
148const jurassicPark = new ParkManagementSystem();
149
150// Adding a location
151jurassicPark.addLocation({
152 id: "LOC-001",
153 name: "T-Rex Enclosure",
154 type: "enclosure",
155 coordinates: [23.45, -67.89],
156 requiredAccessLevel: 4
157});
158
159// Adding a species
160jurassicPark.addSpecies({
161 name: "Tyrannosaurus Rex",
162 geologicalEra: "Cretaceous",
163 type: "predator",
164 averageWeight: 7000,
165 averageAge: 30,
166 dangerLevel: 5,
167 dietRequirements: ["large amounts of meat", "calcium supplementation"],
168 habitatRequirements: ["large area", "natural vegetation", "water access"]
169});
170
171// Adding an employee
172jurassicPark.addEmployee({
173 id: "EMP-001",
174 firstName: "Owen",
175 lastName: "Grady",
176 accessLevel: 5,
177 hireDate: new Date("2010-06-15")
178});
179
180// Adding a specimen
181jurassicPark.addSpecimen({
182 id: "DINO-001",
183 species: "Tyrannosaurus Rex",
184 firstName: "Rexy",
185 age: 7,
186 weight: 7500,
187 gender: "female",
188 location: "LOC-001",
189 healthStatus: "good",
190 lastExamination: new Date("2023-03-20"),
191 rfidTag: "RFID-TREX-001"
192});
193
194// Generating a report
195const report = jurassicPark.generateParkStatusReport();
196console.log("Jurassic Park Status Report:");
197console.log(`Number of employees: ${report.employeeCount}`);
198console.log(`Number of locations: ${report.locationCount}`);
199console.log(`Number of species: ${report.speciesCount}`);
200console.log(`Number of specimens: ${report.specimenCount}`);
201console.log("Specimen health status:", report.specimenHealthStatus);Summary
Interfaces in TypeScript are a powerful tool for modeling data structures and defining contracts in code. In the context of managing Jurassic Park, they allow us to precisely define what the various systems, procedures and park elements should look like.
| Interface feature | Use in Jurassic Park |
|---|---|
| Basic definition | Data structures for dinosaurs, employees, locations |
| Optional properties | Additional information that may or may not be available |
| Readonly properties | Data that should not be changed, e.g. genetic IDs |
| Function interfaces | Definitions of safety procedures and protocols |
| Indexable types | Dynamic databases of dinosaurs and resources |
| Class interfaces | Standards for security and monitoring systems |
| Extending interfaces | Inheritance of traits between dinosaur species |
| Declaration merging | Extending protocols with additional procedures |
Dr. Wu summarizes: "Interfaces in TypeScript, like our park protocols, ensure that every element of the system works as expected. They allow us to build complex systems with confidence that individual components will work together - which is absolutely crucial when dealing with species that can be dangerous if something goes wrong."
Code for this lesson: index.ts
1// Interfaces in Jurassic Park
2console.log("TypeScript interfaces\n");
3
4// ===========================================
5// 1. Basic interfaces
6// ===========================================
7console.log("=== BASIC INTERFACES ===");
8
9// A simple interface
10interface Dinosaur {
11 name: string;
12 species: string;
13 age: number;
14 weight: number;
15}
16
17const trex: Dinosaur = {
18 name: "Rexy",
19 species: "Tyrannosaurus Rex",
20 age: 5,
21 weight: 8000
22};
23
24console.log("T-Rex:", trex);
25
26// ===========================================
27// 2. Optional properties
28// ===========================================
29console.log("\n=== OPTIONAL PROPERTIES ===");
30
31interface DinosaurWithOptionals {
32 name: string;
33 species: string;
34 age: number;
35 nickname?: string; // optional
36 medicalNotes?: string; // optional
37}
38
39const blue: DinosaurWithOptionals = {
40 name: "Blue",
41 species: "Velociraptor",
42 age: 3,
43 nickname: "The Beta"
44 // medicalNotes omitted - OK
45};
46
47console.log("Blue:", blue);
48console.log("Has medical notes:", blue.medicalNotes !== undefined);
49
50// ===========================================
51// 3. Readonly properties
52// ===========================================
53console.log("\n=== READONLY PROPERTIES ===");
54
55interface DinosaurWithReadonly {
56 readonly id: string; // cannot be changed
57 readonly dnaSequence: string; // cannot be changed
58 name: string; // can be changed
59 age: number; // can be changed
60}
61
62const dino: DinosaurWithReadonly = {
63 id: "DINO-001",
64 dnaSequence: "ACGT...",
65 name: "Rex",
66 age: 5
67};
68
69// dino.id = "DINO-002"; // Error: Cannot assign to 'id'
70dino.name = "Rexy"; // OK
71dino.age = 6; // OK
72
73console.log("Dinosaur:", dino);
74
75// ===========================================
76// 4. Methods in interfaces
77// ===========================================
78console.log("\n=== METHODS IN INTERFACES ===");
79
80interface DinosaurWithMethods {
81 name: string;
82 species: string;
83 energy: number;
84
85 // Methods
86 roar(): string;
87 eat(amount: number): void;
88 sleep(hours: number): void;
89 getStatus(): string;
90}
91
92class TyrannosaurusRex implements DinosaurWithMethods {
93 name: string;
94 species: string;
95 energy: number;
96
97 constructor(name: string) {
98 this.name = name;
99 this.species = "Tyrannosaurus Rex";
100 this.energy = 100;
101 }
102
103 roar(): string {
104 this.energy -= 5;
105 return `${this.name} roars: ROAAAAAR!`;
106 }
107
108 eat(amount: number): void {
109 this.energy += amount * 2;
110 if (this.energy > 100) this.energy = 100;
111 console.log(`${this.name} ate ${amount}kg. Energy: ${this.energy}`);
112 }
113
114 sleep(hours: number): void {
115 this.energy += hours * 10;
116 if (this.energy > 100) this.energy = 100;
117 console.log(`${this.name} slept ${hours}h. Energy: ${this.energy}`);
118 }
119
120 getStatus(): string {
121 if (this.energy > 70) return "Energetic";
122 if (this.energy > 30) return "Normal";
123 return "Tired";
124 }
125}
126
127const rexy = new TyrannosaurusRex("Rexy");
128console.log(rexy.roar());
129rexy.eat(50);
130console.log("Status:", rexy.getStatus());
131
132// ===========================================
133// 5. Index signatures
134// ===========================================
135console.log("\n=== INDEX SIGNATURES ===");
136
137// Dynamic keys
138interface DinosaurCollection {
139 [id: string]: Dinosaur;
140}
141
142const collection: DinosaurCollection = {
143 "T-001": trex,
144 "V-001": blue
145};
146
147console.log("Collection:", collection);
148console.log("T-001:", collection["T-001"]);
149
150// Mixed properties
151interface PaddockData {
152 id: string;
153 capacity: number;
154 [key: string]: any; // other dynamic properties
155}
156
157const paddock: PaddockData = {
158 id: "P-01",
159 capacity: 10,
160 securityLevel: "high",
161 temperature: 25,
162 humidity: 60
163};
164
165console.log("Paddock:", paddock);
166
167// ===========================================
168// 6. Functions in interfaces
169// ===========================================
170console.log("\n=== FUNCTIONS IN INTERFACES ===");
171
172// Function type
173interface DinosaurFilter {
174 (dino: Dinosaur): boolean;
175}
176
177const carnivoreFilter: DinosaurFilter = (dino) => {
178 return dino.species.includes("saurus") && dino.weight > 1000;
179};
180
181console.log("Is T-Rex carnivore:", carnivoreFilter(trex));
182
183// Interface for functions with properties
184interface DinosaurValidator {
185 (dino: Dinosaur): boolean;
186 errorMessage: string;
187}
188
189const ageValidator: DinosaurValidator = (dino) => {
190 return dino.age >= 0 && dino.age <= 100;
191};
192ageValidator.errorMessage = "Age must be between 0 and 100";
193
194console.log("Validator:", ageValidator(trex));
195console.log("Error message:", ageValidator.errorMessage);
196
197// ===========================================
198// 7. Nested interfaces
199// ===========================================
200console.log("\n=== NESTED INTERFACES ===");
201
202interface Location {
203 latitude: number;
204 longitude: number;
205 altitude: number;
206}
207
208interface Paddock {
209 id: string;
210 name: string;
211 location: Location; // nested interface
212 dimensions: {
213 width: number;
214 length: number;
215 height: number;
216 };
217 dinosaurs: Dinosaur[];
218}
219
220const trexPaddock: Paddock = {
221 id: "P-01",
222 name: "T-Rex Territory",
223 location: {
224 latitude: 22.3964,
225 longitude: -159.5261,
226 altitude: 50
227 },
228 dimensions: {
229 width: 1000,
230 length: 1500,
231 height: 50
232 },
233 dinosaurs: [trex]
234};
235
236console.log("Paddock:", trexPaddock);
237console.log("Location:", trexPaddock.location);
238
239// ===========================================
240// 8. Hybrid types
241// ===========================================
242console.log("\n=== HYBRID TYPES ===");
243
244interface Counter {
245 (start: number): string;
246 interval: number;
247 reset(): void;
248}
249
250function createCounter(): Counter {
251 let count = 0;
252
253 const counter = function(start: number) {
254 count = start;
255 return `Count: ${count}`;
256 } as Counter;
257
258 counter.interval = 1;
259 counter.reset = function() {
260 count = 0;
261 };
262
263 return counter;
264}
265
266const myCounter = createCounter();
267console.log(myCounter(5));
268console.log("Interval:", myCounter.interval);
269myCounter.reset();
270
271// ===========================================
272// 9. Summary
273// ===========================================
274console.log("\n=== SUMMARY ===");
275console.log("Basic interfaces - object structure");
276console.log("Optional properties - ?");
277console.log("Readonly - immutable properties");
278console.log("Methods - functions in interfaces");
279console.log("Index signatures - dynamic keys");
280console.log("Nested interfaces - complex structures");
281
282console.log("\nInterfaces mastered!");Spotted a mistake in this lesson?
Check yourself
Answer the questions from this lesson. Pick an answer to see right away whether it is correct.
1. How does an interface differ from a type alias in TypeScript?
2. How do you mark an interface property as optional in TypeScript?
Hands-on tasks in the game
- Code editor
Define a Dinosaur interface with fields name: string, species: string, weight?: number and a method roar(): void.
- Horizontal ordering
Arrange the elements of a TypeScript interface definition:
- Click in order
Arrange the elements of a readonly field definition in an interface:
- Vertical ordering
Order interface concepts from simplest to most advanced: