Skip to Content
Course content

148: Member Visibility: public, private, protected

Click on the "Edit" button in the top corner of the screen to edit your slide content.

By now, you're comfortable with classes and how to instantiate them. But as your projects grow, you'll find that letting any part of your code touch any property of a class is a recipe for disaster. That's where member visibility comes in. It's essentially your way of drawing boundaries around your data.

Do I really need to mark everything as public?

The short answer is: no. In TypeScript, if you don't specify a visibility modifier, it defaults to public. I usually omit the public keyword entirely because it just adds noise to the code. If a property is public, it means any piece of code that has a reference to the instance can read or change it.

class GameCharacter {
  name: string; // implicitly public
  health: number = 100; // implicitly public

  constructor(name: string) {
    this.name = name;
  }
}

const hero = new GameCharacter("Aragorn");
hero.health = 0; // This works, but maybe we don't want it to be this easy?

When should I use private versus protected?

This is where most people get tripped up. Both prevent outside code from touching your properties, but they treat "children" (subclasses) differently. Use private when a property is a secret that only that specific class should know about. Use protected when you want your subclasses to have access, but you still want to keep the rest of the world out.

Think about a character's internal ID versus their stamina. The ID should be private; the stamina might be something a Warrior subclass needs to modify during a "Power Attack," but the MainMenu shouldn't be able to just set it to 999.

class GameCharacter {
  private internalId: string = "ID_12345"; 
  protected stamina: number = 50;

  public getInfo() {
    console.log(`ID: ${this.internalId}`); // Works: inside the class
  }
}

class Warrior extends GameCharacter {
  public attack() {
    this.stamina -= 10; // Works: stamina is protected
    // this.internalId = "NEW_ID"; // Error: internalId is private to GameCharacter
  }
}

const myWarrior = new Warrior();
// myWarrior.stamina = 100; // Error: stamina is protected and not accessible outside the class hierarchy

Does the private keyword actually stop someone from hacking the data at runtime?

Here is the "gotcha" that catches a lot of developers: TypeScript's private and protected modifiers are compile-time checks. Once the code is transpiled to JavaScript, those modifiers vanish. If someone is determined enough, they can still access those properties in the browser console.

If you need "hard" privacy that exists even in the compiled JavaScript, you should use the JavaScript private class fields syntax (the # prefix). I generally stick to the TypeScript private keyword for internal team organization, but I use # when I'm building a library where I absolutely cannot allow the end-user to touch a specific variable.

class BankAccount {
  #secretPin: string; // Hard runtime privacy

  constructor(pin: string) {
    this.#secretPin = pin;
  }
}

const account = new BankAccount("1234");
// console.log(account.#secretPin); // This is a syntax error in both TS and JS



📋 Practical Task

Implementing a Protected Inventory System for RPG Characters

You are building a combat system. Your goal is to ensure that a character's inventory can be modified by the character and their subclasses, but not by the external game engine logic.

  • Create a base class Character with a protected array called inventory (strings) and a private property called characterId.
  • Create a subclass Mage that extends Character.
  • In the Mage class, implement a method castSpell(spellName: string) that adds the spell name to the inventory array.
  • In the Mage class, try to create a method that changes the characterId and observe the TypeScript error.
  • Instantiate a Mage object and attempt to push an item directly into the inventory array from outside the class to confirm it is blocked.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.