// public = anywhere, private = same class only, protected = class + subclasses
Note TypeScript access modifiers are compile-time only — at runtime, everything is accessible. For true runtime privacy, use JavaScript's native #private fields (e.g., #balance). The public modifier is the default and can be omitted.
// Adding an access modifier to a constructor param auto-declares and assigns the property
Note Parameter properties reduce boilerplate by combining declaration, constructor parameter, and assignment into one. You can combine them with readonly. Regular (unmodified) parameters are not turned into properties — only those prefixed with public, private, protected, or readonly.
parameter propertyconstructor shorthandauto assign constructorshorthand class property
Abstract Classes
syntax
abstract class Name {
abstract method(): Type;
concreteMethod(): Type { ... }
}
example
abstract class Shape {
abstract area(): number;
abstract perimeter(): number;
describe(): string {
return`Area: ${this.area().toFixed(2)}, Perimeter: ${this.perimeter().toFixed(2)}`;
}
}
class Circle extends Shape {
constructor(private radius: number) {
super();
}
area(): number {
return Math.PI * this.radius ** 2;
}
perimeter(): number {
return2 * Math.PI * this.radius;
}
}
// const shape = new Shape(); // Error: Cannot instantiate abstract classconst circle = new Circle(5);
console.log(circle.describe());
output
// "Area: 78.54, Perimeter: 31.42"
Note Abstract classes cannot be instantiated directly. They can contain both abstract members (no implementation — subclasses must provide them) and concrete members (shared implementation). Use abstract classes when subclasses share behavior; use interfaces when they only share shape.
class Child extends Parent {
override method(): Type { ... }
}
example
class Transport {
getSpeed(): number {
return0;
}
describe(): string {
return`Speed: ${this.getSpeed()} km/h`;
}
}
class Train extends Transport {
override getSpeed(): number {
return300;
}
// override getSped(): number { // Error with noImplicitOverride:// return 300; // 'getSped' does not exist on base// }
}
output
// override keyword verifies the method actually exists on the parent class
Note Enable noImplicitOverride in tsconfig to require the override keyword on all overriding methods. This catches typos (overriding a method that does not exist on the parent) and refactoring bugs (parent method was renamed but child was not updated).
// Calling processOrder with ["ord_123"]
// Processing ord_123
Note TS 5.0 introduced TC39 standard decorators — these are different from the legacy experimental decorators. Standard decorators receive a context object instead of the old three-parameter signature. Set "experimentalDecorators": false (or omit it) to use the new standard. Legacy decorators are still available with "experimentalDecorators": true.
// A class can implement multiple interfaces, enforcing all their contracts
Note implements is purely a compile-time check — it does not inherit any code. Each property and method must be explicitly defined in the class. If the class already matches the interface shape, implements is optional but serves as documentation and catches regressions.
class implementsmultiple interfacesclass contractserializable patternimplement multiple