Skip to main content
eLearner.app

End of the TypeScript Course

Summary and final challenge

Congratulations! You have completed all 5 modules of the TypeScript Course — from basic type annotations and primitive types to robust programming with Interfaces, Unions, highly versatile Generics, Classes/Utility Types, and Advanced Types/Guards. Below is a map of what you have mastered and a five-step final challenge.

Reminder: TypeScript exercises are verified statically (keywords). To actually run the code, each exercise provides a TypeScript Playground button that copies the code and opens typescriptlang.org/play.

01 · Fundamentals

  • annotations
  • primitive types
  • explicit vs implicit
  • arrays string[] / number[]
  • fixed tuples

02 · Types and Interfaces

  • interface
  • type alias
  • optional fields ?
  • union types |
  • type narrowing (typeof)

03 · Generics and Functions

  • typed functions
  • optional parameters
  • type signatures
  • generics <T>
  • generic classes and boxes

04 · Classes and Utility Types

  • classes and constructors
  • access modifiers (private/public)
  • interface implementation
  • utility types (Partial, Omit)
  • encapsulation best practices

05 · Advanced Types and Guards

  • type guards
  • is operator
  • typeof / instanceof
  • literal types
  • assertions as / as const
  • template literal types

The final challenge, in five steps

Combine what you have learned about TypeScript by building five small logical components: a generic array element retriever, an employee data helper with optional fields, an API response handler using discriminated unions, a task management system using classes/utility types, and a dashboard permission manager using custom type guards.

1 · First generic element

Write a generic function that accepts an array of elements of type T and returns the first element (or undefined if the array is empty). Module 3 (Generics).

Exercise#ts.boss.e1
Attempts: 0Loading…

Define the generic function firstElement<T>(arr: T[]): T | undefined that returns the first element of the array.

Loading editor…
Show hint

Use the generic signature <T> before parameters. The function should return arr[0] or undefined.

Solution available after 3 attempts

2 · Optional employee data helper

Define an Employee interface with an optional salary field, and a getSalary function that returns the salary or 0 if it is not specified. Module 2 (Interfaces and optional fields).

Exercise#ts.boss.e2
Attempts: 0Loading…

Create the Employee interface with id (number), name (string), and salary (optional number). Write getSalary(emp: Employee): number to check if salary is defined before returning it.

Loading editor…
Show hint

Use the question mark salary?: number in the interface and the nullish coalescing operator (??) in the function.

Solution available after 3 attempts

3 · Discriminated union for API response

Define a type to handle an API response that can be either a success (with generic data) or a failure (with a string message). Module 2 (Unions and Narrowing) + Module 3 (Generics).

Exercise#ts.boss.e3
Attempts: 0Loading…

Create ApiResponse<T> as a union of Success<T> (status: "success", data: T) and Failure (status: "error", message: string). Write handleResponse<T>(res: ApiResponse<T>): string that checks res.status and returns either "Data: " + res.data or "Error: " + res.message.

Loading editor…
Show hint

Check res.status === "success" to narrow down the union type at runtime.

Solution available after 3 attempts

4 · Task Manager Class

Define a NewTask type alias that omits id and completed from an existing Task interface, and implement a TaskManager class that manages a private array of Tasks. Module 4 (Classes and Utility Types).

Exercise#ts.boss.e4
Attempts: 0Loading…

Define the NewTask type by omitting id and completed from Task. Create the TaskManager class implementing ITaskManager, managing a private tasks array and a nextId counter starting from 1 to assign sequential IDs in the addTask method.

Loading editor…
Show hint

Use type NewTask = Omit<Task, "id" | "completed">; to exclude the keys. In the class, define private tasks: Task[] = []; and private nextId: number = 1;.

Solution available after 3 attempts

5 · Type guards and permissions

Define a NormalUser or Admin type with discriminated unions. Write a custom type guard isAdmin and a getDashboardAccess function to return a specific access string depending on the user role. Module 5 (Advanced Types and Guards).

Exercise#ts.boss.e5
Attempts: 0Loading…

Define the type guard isAdmin(user: User): user is Admin that checks if user.role === "admin". Then write the function getDashboardAccess(user: User): string that uses the isAdmin guard to return "Admin Access: " + user.permissions.join(", ") for admins, or "Standard Access for " + user.username for standard users.

Loading editor…
Show hint

Use function isAdmin(user: User): user is Admin { return user.role === "admin"; }. In the getDashboardAccess function, use an if block to test isAdmin(user) before accessing the permissions property.

Solution available after 3 attempts

Printable Cheatsheet

A single page with all the essential syntax of modern TypeScript, ready to keep handy while you code.

Open the cheatsheet

What now?

Consistent practice is the best way to strengthen your skills. Open the TypeScript Playground to experiment freely with complex scenarios or to prepare your code snippets before testing them in your actual projects.