Managing Product Reviews and Data Aggregation in TypeScript

Introduction

Hello, and welcome to the first lesson in this course! We are going to dive into the world of managing product reviews and applying data aggregation in practice. We will start with a relatively simple Starter Task to set up our base and then gradually build up to a more complex solution involving data aggregation. Let's jump in!

Starter Task: Methods and Their Definitions

For our starter task, we will lay the foundation by implementing basic operations for managing product reviews. These are the methods we will need to implement, with TypeScript-specific type annotations:

  • addReview(productId: string, reviewId: string, reviewText: string, rating: number): boolean — This method adds a review to the product specified by productId. If a review with reviewId already exists, it updates the existing review. The review contains a flagged field, which indicates whether the review is marked as inappropriate (by default, this field is set to false). Returns true if the review was added or updated successfully, false otherwise.

  • getReview(productId: string, reviewId: string): { text: string; rating: number; flagged: boolean } | null — Returns the review details (reviewText, rating, and flagged fields) for the review specified by reviewId under the given productId. If the review or product does not exist, it returns null.

  • deleteReview(productId: string, reviewId: string): boolean — Deletes the review specified by reviewId under the given productId. Returns true if the review was deleted, false otherwise.

Starter Task Implementation

Let's look at the code that implements these functionalities in TypeScript:

TypeScript
type Review = {
    text: string;
    rating: number;
    flagged: boolean;
};

class ReviewManager {
    private products: Record<string, Record<string, Review>> = {};

    addReview(productId: string, reviewId: string, reviewText: string, rating: number): boolean {
        if (rating < 1 || rating > 5) {
            return false;
        }
        if (!this.products[productId]) {
            this.products[productId] = {};
        }
        this.products[productId][reviewId] = { text: reviewText, rating: rating, flagged: false };
        return true;
    }

    getReview(productId: string, reviewId: string): { text: string; rating: number; flagged: boolean } | null {
        if (this.products[productId] && this.products[productId][reviewId]) {
            const review = this.products[productId][reviewId];
            return { text: review.text, rating: review.rating, flagged: review.flagged };
        }
        return null;
    }

    deleteReview(productId: string, reviewId: string): boolean {
        if (this.products[productId] && this.products[productId][reviewId]) {
            delete this.products[productId][reviewId];
            if (Object.keys(this.products[productId]).length === 0) {
                delete this.products[productId];
            }
            return true;
        }
        return false;
    }
}

// Instantiate the ReviewManager
const reviewManager = new ReviewManager();

// Adding some reviews
reviewManager.addReview("p1", "r1", "Great product!", 5);
reviewManager.addReview("p1", "r2", "Not bad", 3);

// Testing getReview method
console.log(reviewManager.getReview("p1", "r1")); // Expected: { text: "Great product!", rating: 5, flagged: false }
console.log(reviewManager.getReview("p1", "r3")); // Expected: null

// Testing deleteReview method
console.log(reviewManager.deleteReview("p1", "r2")); // Expected: true
console.log(reviewManager.getReview("p1", "r2")); // Expected: null

This code establishes the foundational methods for managing product reviews within a ReviewManager class. The addReview method allows adding or updating reviews with valid ratings between 1 and 5, creating a product entry if it doesn’t exist. The getReview method retrieves details for a specific product and review, returning null if either doesn’t exist. The deleteReview method removes a review and deletes the product entry if no reviews remain.

The Record type, used for the products property, is a TypeScript utility that defines an object structure with specific key-value mappings. Here, Record<string, Record<string, Review>> maps a productId (outer string key) to another object, which maps a reviewId (inner string key) to its corresponding Review. This ensures a structured and type-safe representation of products and their associated reviews, simplifying the management of nested data.

Now, let's extend this with new features.

Sign up

Join the 1M+ learners on CodeSignal

Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal