OOP Architecture

Preview — 3 of 10 questions

Why does this code fail?

javascript
abstract class Animal {
  abstract speak(): string;
}

type Constructor<T> = new (...args: any[]) => T;

function instantiate<T>(Ctor: Constructor<T>): T {
  return new Ctor();
}

instantiate(Animal); // ?
AIt works — abstract classes are constructors
BError — Animal is abstract; it cannot be assigned to Constructor<T> which requires a non-abstract constructor
CError — instantiate requires a second argument
DWorks but returns null

How do you make a builder type-safe at compile time?

javascript
type BuilderState = {
  name?: string;
  age?: number;
  email?: string;
};

class UserBuilder<TState extends BuilderState = {}> {
  private state: TState = {} as TState;

  setName(name: string): UserBuilder<TState & { name: string }> {
    return Object.assign(
      new UserBuilder<TState & { name: string }>(),
      { state: { ...this.state, name } }
    );
  }

  build(this: UserBuilder<{ name: string; age: number; email: string }>): Required<BuilderState> {
    return this.state as Required<BuilderState>;
  }
}
Abuild() can be called at any point regardless of state
BThe builder pattern requires runtime validation, not TypeScript types
CThe type parameter TState defaults to any so all states are equivalent
Dbuild() is only callable when the builder's state includes name, age, and email — TypeScript enforces the constraint at compile time

What role does TypeScript play in this DI pattern?

javascript
interface ILogger {
  log(msg: string): void;
}

interface IUserRepository {
  findById(id: string): Promise<User | null>;
}

class UserService {
  constructor(
    private logger: ILogger,
    private userRepo: IUserRepository
  ) {}

  async getUser(id: string): Promise<User | null> {
    this.logger.log(`Fetching user ${id}`);
    return this.userRepo.findById(id);
  }
}
ATypeScript enforces that only specific classes can be injected
BTypeScript generates the DI container automatically
CTypeScript enforces the interface contract — any class implementing ILogger and IUserRepository can be injected, enabling testability via mock implementations
DInterfaces make DI slower at runtime

Sign up free to play

Answer all 10 questions (7 more), see explanations for every answer, and track your score.