Bird
Raised Fist0
Typescriptprogramming~20 mins

Generic repository pattern in Typescript - Practice Problems & Coding Challenges

Choose your learning style10 modes available
Challenge - 5 Problems
🎖️
Generic Repository Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ Predict Output
intermediate
2:00remaining
Output of generic repository save method
What is the output of this TypeScript code using a generic repository pattern?
Typescript
interface IEntity {
  id: number;
}

class GenericRepository<T extends IEntity> {
  private items: T[] = [];

  save(item: T): string {
    this.items.push(item);
    return `Saved item with id: ${item.id}`;
  }
}

const repo = new GenericRepository<{id: number; name: string}>();
console.log(repo.save({id: 1, name: 'Test'}));
ATypeError at runtime
B"Saved item with id: undefined"
CCompilation error due to missing id property
D"Saved item with id: 1"
Attempts:
2 left
💡 Hint
Check how the generic type extends IEntity and the id property is accessed.
🧠 Conceptual
intermediate
1:30remaining
Purpose of generic repository pattern
What is the main purpose of using a generic repository pattern in TypeScript?
ATo replace all interfaces with classes
BTo enforce UI styling rules across components
CTo create a reusable data access layer for different entity types
DTo handle HTTP requests directly in components
Attempts:
2 left
💡 Hint
Think about code reuse and data management.
🔧 Debug
advanced
2:00remaining
Identify the error in generic repository update method
What error will this TypeScript code produce when trying to update an item in the generic repository?
Typescript
interface IEntity {
  id: number;
}

class GenericRepository<T extends IEntity> {
  private items: T[] = [];

  update(item: T): boolean {
    const index = this.items.findIndex(i => i.id === item.id);
    if (index !== -1) {
      this.items[index] = item;
      return true;
    }
    return false;
  }
}

const repo = new GenericRepository<{id: number; name: string}>();
repo.update({id: 1, name: 'Updated'});
AReturns false because item with id 1 does not exist
BThrows runtime error because items array is undefined
CCompilation error due to missing constructor
DReturns true but does not update the item
Attempts:
2 left
💡 Hint
Check the initial state of the items array before update.
📝 Syntax
advanced
1:30remaining
Correct generic constraint syntax
Which option correctly declares a generic repository class constrained to entities with an id property?
Aclass GenericRepository<T where T.id: number> {}
Bclass GenericRepository<T extends {id: number}> {}
Cclass GenericRepository<T: {id: number}> {}
Dclass GenericRepository<T with id: number> {}
Attempts:
2 left
💡 Hint
Remember TypeScript syntax for generic constraints uses extends.
🚀 Application
expert
2:30remaining
Number of items after operations in generic repository
Given this TypeScript code using a generic repository, how many items are in the repository after all operations?
Typescript
interface IEntity { id: number; }

class GenericRepository<T extends IEntity> {
  private items: T[] = [];

  save(item: T): void {
    this.items.push(item);
  }

  delete(id: number): boolean {
    const index = this.items.findIndex(i => i.id === id);
    if (index !== -1) {
      this.items.splice(index, 1);
      return true;
    }
    return false;
  }

  count(): number {
    return this.items.length;
  }
}

const repo = new GenericRepository<{id: number; name: string}>();
repo.save({id: 1, name: 'A'});
repo.save({id: 2, name: 'B'});
repo.delete(1);
repo.save({id: 3, name: 'C'});
repo.delete(4);
const total = repo.count();
console.log(total);
A2
B3
C1
D0
Attempts:
2 left
💡 Hint
Track each save and delete operation carefully.

Practice

(1/5)
1.

What is the main benefit of using the Generic Repository Pattern in TypeScript?

easy
A. It allows handling multiple data types with one reusable class.
B. It automatically generates UI components.
C. It replaces the need for TypeScript interfaces.
D. It compiles TypeScript code faster.

Solution

  1. Step 1: Understand the purpose of the generic repository

    The generic repository pattern is designed to handle data operations for many types using one class or interface.
  2. Step 2: Compare options with the pattern's purpose

    Only It allows handling multiple data types with one reusable class. correctly describes this benefit. Options A, B, and C are unrelated to the pattern's main use.
  3. Final Answer:

    It allows handling multiple data types with one reusable class. -> Option A
  4. Quick Check:

    Generic repository = reusable data handler [OK]
Hint: Generic means reusable for many types [OK]
Common Mistakes:
  • Thinking it generates UI components
  • Confusing it with TypeScript compilation
  • Believing it removes interfaces
2.

Which of the following is the correct way to declare a generic repository interface in TypeScript?

interface IRepository<T> {
  add(item: T): void;
  get(id: number): T | undefined;
}
easy
A. interface IRepository<T> { add(item: T): void; get(id: number): T | undefined; }
B. interface IRepository { add(item: any): void; get(id: number): any; }
C. interface IRepository<T> { add(item: any): void; get(id: number): T; }
D. interface IRepository<T> { add(item: T): T; get(id: string): T | undefined; }

Solution

  1. Step 1: Check generic syntax correctness

    interface IRepository<T> { add(item: T): void; get(id: number): T | undefined; } correctly declares a generic interface with type parameter <T> and uses it consistently in method signatures.
  2. Step 2: Validate method signatures

    interface IRepository<T> { add(item: T): void; get(id: number): T | undefined; }'s methods use item: T and return T | undefined for get, which is correct. Other options misuse types or parameter types.
  3. Final Answer:

    interface IRepository<T> { add(item: T): void; get(id: number): T | undefined; } -> Option A
  4. Quick Check:

    Generic interface syntax = interface IRepository<T> { add(item: T): void; get(id: number): T | undefined; } [OK]
Hint: Generic interfaces use <T> and consistent types [OK]
Common Mistakes:
  • Using 'any' instead of generic type T
  • Mismatching parameter and return types
  • Using wrong id parameter type
3.

Given the following generic repository class, what will be the output of the console.log statement?

class Repository<T> {
  private items: T[] = [];
  add(item: T): void {
    this.items.push(item);
  }
  getAll(): T[] {
    return this.items;
  }
}

const repo = new Repository<string>();
repo.add('apple');
repo.add('banana');
console.log(repo.getAll());
medium
A. Error: Type mismatch
B. ['apple']
C. []
D. ['apple', 'banana']

Solution

  1. Step 1: Understand the generic repository usage

    The repository is created for strings, so it stores string items in an array.
  2. Step 2: Trace the add and getAll methods

    Two strings 'apple' and 'banana' are added, so getAll returns ['apple', 'banana'].
  3. Final Answer:

    ['apple', 'banana'] -> Option D
  4. Quick Check:

    Added items = ['apple', 'banana'] [OK]
Hint: Add items then getAll returns all added [OK]
Common Mistakes:
  • Expecting only one item in output
  • Thinking getAll returns empty array
  • Confusing type errors
4.

Identify the error in this generic repository implementation:

class Repository<T> {
  private items: T[] = [];
  add(item: T): void {
    this.items.push(item);
  }
  get(id: number): T {
    return this.items[id];
  }
}

const repo = new Repository<number>();
console.log(repo.get(0));
medium
A. The items array should be public, not private.
B. The add method should return the added item.
C. The get method should return T | undefined to handle missing items.
D. The generic type T cannot be used with arrays.

Solution

  1. Step 1: Analyze the get method return type

    The get method returns this.items[id], which may be undefined if the index is invalid.
  2. Step 2: Check return type compatibility

    Since undefined is possible, the return type should be T | undefined to avoid runtime errors.
  3. Final Answer:

    The get method should return T | undefined to handle missing items. -> Option C
  4. Quick Check:

    Return type must allow undefined for missing index [OK]
Hint: Allow undefined return for invalid index [OK]
Common Mistakes:
  • Ignoring possible undefined return
  • Changing add method unnecessarily
  • Making items public without reason
5.

You want to create a generic repository that supports updating an item by id. Which method signature correctly fits this requirement?

hard
A. update(item: T): void
B. update(id: number, item: T): boolean
C. update(id: string, item: any): T
D. update(id: number): T | undefined

Solution

  1. Step 1: Understand update method needs

    To update an item, you need to specify which item by id and provide the new item data.
  2. Step 2: Evaluate method signatures

    update(id: number, item: T): boolean takes an id and a new item of type T, returning boolean to indicate success, which fits the requirement best.
  3. Final Answer:

    update(id: number, item: T): boolean -> Option B
  4. Quick Check:

    Update needs id and new item, returns success [OK]
Hint: Update needs id and new item, returns success boolean [OK]
Common Mistakes:
  • Missing id parameter
  • Using wrong parameter types
  • Returning wrong type from update
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard