# TypeScript Access Modifiers

TypeScript provides access modifiers to control the visibility of class members (properties and methods). This encapsulates data and prevents unauthorized access or modification.

## 1. `public` (Default)

By default, all members of a class in TypeScript are `public`. They can be accessed anywhere (inside the class, in subclasses, and outside the class).

```typescript
class Animal {
  public name: string; // 'public' is optional here

  constructor(name: string) {
    this.name = name;
  }

  public move(distance: number) {
    console.log(`${this.name} moved ${distance}m.`);
  }
}

const cat = new Animal("Cat");
cat.move(10); // OK
console.log(cat.name); // OK
```

## 2. `private`

Members marked as `private` cannot be accessed from outside of its containing class, including subclasses.

```typescript
class Animal {
  private name: string;

  constructor(name: string) {
    this.name = name;
  }
}

class Dog extends Animal {
  bark() {
    // Error: Property 'name' is private and only accessible within class 'Animal'.
    // console.log(this.name); 
  }
}

const dog = new Animal("Dog");
// Error: Property 'name' is private.
// console.log(dog.name); 
```

## 3. `protected`

The `protected` modifier acts like `private`, with the exception that members are also accessible within deriving classes (subclasses).

```typescript
class Person {
  protected name: string;

  constructor(name: string) {
    this.name = name;
  }
}

class Employee extends Person {
  private department: string;

  constructor(name: string, department: string) {
    super(name);
    this.department = department;
  }

  public getElevatorPitch() {
    // OK: Can access protected 'name' from subclass
    return `Hello, my name is ${this.name} and I work in ${this.department}.`;
  }
}

const howard = new Employee("Howard", "Sales");
console.log(howard.getElevatorPitch());
// Error: Property 'name' is protected and only accessible within class 'Person' and its subclasses.
// console.log(howard.name); 
```

## 4. `readonly` Modifier

You can make properties read-only by using the `readonly` keyword. Read-only properties must be initialized at their declaration or in the constructor.

```typescript
class Octopus {
  readonly name: string;
  readonly numberOfLegs: number = 8;

  constructor(theName: string) {
    this.name = theName;
  }
}

let dad = new Octopus("Man with the 8 strong legs");
// dad.name = "Man with the 3-piece suit"; // Error: name is readonly
```

## 5. Parameter Properties (Shorthand)

TypeScript offers a shorthand to declare and initialize a class member in one place by adding an access modifier to the constructor parameter.

```typescript
class User {
  // Instead of declaring 'name' above and assigning it in the body...
  constructor(public name: string, private age: number) {
    // No body assignment needed!
  }
}

const user = new User("Alice", 30);
console.log(user.name); // Alice
// console.log(user.age); // Error: age is private
```

## 6. TypeScript `private` vs JavaScript `#private`

TypeScript's `private` is a compile-time check. At runtime (in the generated JavaScript), the property is just a normal property and can be accessed if you ignore type checking.

Modern JavaScript (ES2020) introduced **Private Fields** using the `#` syntax, which guarantees hard runtime privacy.

```typescript
class Container {
  private tsPrivate = "I am hidden at compile time";
  #jsPrivate = "I am hidden at runtime";

  print() {
    console.log(this.tsPrivate);
    console.log(this.#jsPrivate);
  }
}

const c = new Container();
// (c as any).tsPrivate; // Works at runtime (though TS complains)
// (c as any).#jsPrivate; // Syntax Error / Runtime Error: Private field '#jsPrivate' must be declared in an enclosing class
```

[[programming/javascript/typescript/typescript]]