Welcome! Today, we are going to explore an engaging task that involves managing employee records within a company. Specifically, we will work with nested objects and arrays to add projects and tasks for employees and retrieve those tasks as needed. This exercise will help you understand how to manipulate nested data structures efficiently using TypeScript's type safety features.
Let's start by discussing the methods we will implement in our EmployeeRecords
class, utilizing type annotations for method parameters and return types to provide type safety.
addProject(employeeId: string, projectName: string): boolean
— This method adds a new project to an employee's list of projects. If the project already exists for that employee, the method returnsfalse
. Otherwise, it adds the project and returnstrue
.addTask(employeeId: string, projectName: string, task: string): boolean
— This method adds a new task to a specified project for an employee. If the project does not exist for that employee, the method returnsfalse
. If the task is added successfully, it returnstrue
.getTasks(employeeId: string, projectName: string): string[] | null
— This method retrieves all tasks for a specified project of an employee. If the project does not exist for that employee, the method returnsnull
. Otherwise, it returns the list of tasks.
Now, let's build our EmployeeRecords
class step by step, ensuring we understand each component clearly.
TypeScript1type ProjectTasks = { [projectName: string]: string[] }; 2type EmployeeRecordsStorage = { [employeeId: string]: ProjectTasks }; 3 4class EmployeeRecords { 5 private records: EmployeeRecordsStorage = {}; 6 7 constructor() {} 8}
In this initial setup, we define the EmployeeRecords
class with a records
object. The type ProjectTasks
represents an object where project names are the keys and arrays of tasks are the values. EmployeeRecordsStorage
maps employee IDs to their projects and tasks, ensuring flexible and type-safe management of employee records. Each employee ID key corresponds to an object that holds projects and their associated tasks, using TypeScript index signatures.
TypeScript1addProject(employeeId: string, projectName: string): boolean { 2 if (!this.records[employeeId]) { 3 this.records[employeeId] = {}; 4 } 5 if (this.records[employeeId][projectName]) { 6 return false; 7 } else { 8 this.records[employeeId][projectName] = []; 9 return true; 10 } 11}
The addProject
method is used to add a new project to an employee's record. It first checks if the employee exists in the records. If not, it initializes the employee's record with an empty object to store projects. The method then checks if the specified project already exists; if it does, it returns false
. If not, it creates a new entry for the project with an empty array for tasks and returns true
.
TypeScript1addTask(employeeId: string, projectName: string, task: string): boolean { 2 if (!this.records[employeeId] || !this.records[employeeId][projectName]) { 3 return false; 4 } 5 this.records[employeeId][projectName].push(task); 6 return true; 7}
The addTask
method is designed to add a task to a specific project of an employee. Before adding the task, the method verifies if both the employee and the project exist. If either does not exist, it returns false
, indicating the task cannot be added. If both exist, it adds the task to the project's list and returns true
, confirming the successful addition of the task.
TypeScript1getTasks(employeeId: string, projectName: string): string[] | null { 2 return this.records[employeeId] ? this.records[employeeId][projectName] || null : null; 3}
The getTasks
method is used to retrieve all the tasks for a specified project of an employee. It first checks if the employee exists and then verifies the existence of the specified project. If either the employee or project does not exist, the method returns null
. If both exist, it returns the list of tasks associated with the project, allowing easy retrieval of project details.
Below is the complete code for the EmployeeRecords
class, along with examples demonstrating its usage:
TypeScript1type ProjectTasks = { [projectName: string]: string[] }; 2type EmployeeRecordsStorage = { [employeeId: string]: ProjectTasks }; 3 4class EmployeeRecords { 5 private records: EmployeeRecordsStorage = {}; 6 7 addProject(employeeId: string, projectName: string): boolean { 8 if (!this.records[employeeId]) { 9 this.records[employeeId] = {}; 10 } 11 if (this.records[employeeId][projectName]) { 12 return false; 13 } else { 14 this.records[employeeId][projectName] = []; 15 return true; 16 } 17 } 18 19 addTask(employeeId: string, projectName: string, task: string): boolean { 20 if (!this.records[employeeId] || !this.records[employeeId][projectName]) { 21 return false; 22 } 23 this.records[employeeId][projectName].push(task); 24 return true; 25 } 26 27 getTasks(employeeId: string, projectName: string): string[] | null { 28 return this.records[employeeId] ? this.records[employeeId][projectName] || null : null; 29 } 30} 31 32// Example usage 33const records = new EmployeeRecords(); 34console.log(records.addProject("E123", "ProjectA")); // Returns true 35console.log(records.addTask("E123", "ProjectA", "Task1")); // Returns true 36console.log(records.getTasks("E123", "ProjectA")); // Returns ["Task1"] 37console.log(records.getTasks("E123", "NonExistentProject")); // Returns null 38console.log(records.addProject("E123", "ProjectA")); // Returns false
This section showcases the EmployeeRecords
class with the implemented methods, and how they can be effectively utilized to manage employee records with type safety in TypeScript.
In this lesson, we successfully implemented the EmployeeRecords
class for managing projects and tasks for employees using nested objects and arrays in TypeScript. We applied TypeScript's type annotations to provide enhanced type safety and code reliability. By taking advantage of TypeScript's features, you can ensure data integrity and catch errors at compile time, improving the robustness and maintainability of your code. Understanding how to work with nested data structures and type safety allows you to efficiently manage complex data hierarchies, elevating your programming skills.