Two unrelated but very useful class features bundled into one note: static members and parameter properties.
Static members
In simple language, static means “this belongs to the class, not to instances”. Think of it like the only difference is whether we call it on the class itself or on an object made from the class.
class MathHelper {
static PI = 3.14159;
static square(n: number) { return n * n; }
}
MathHelper.PI; // 3.14159
MathHelper.square(4); // 16
const m = new MathHelper();
m.PI; // Error — PI is on the class, not the instance
Static fields are great for:
- Constants (
HttpStatus.OK = 200). - Counters shared across instances.
- Factory methods (
User.fromJSON(...)). - Singleton patterns.
class IdGenerator {
private static counter = 0;
static next() { return ++IdGenerator.counter; }
}
IdGenerator.next(); // 1
IdGenerator.next(); // 2
Static members can be public, private, protected, and readonly — same modifiers as instance members.
Static blocks
Modern TS supports static initialization blocks for setup that needs more than a single expression.
class Config {
static envs: string[];
static {
Config.envs = process.env.NODE_ENV?.split(",") ?? [];
}
}
Parameter properties — the constructor shortcut
This one saves SO much boilerplate. Adding an access modifier (or readonly) to a constructor parameter automatically declares AND assigns it as a field.
// the long way
class User {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
// the short way — parameter properties
class User2 {
constructor(public name: string, public age: number) {}
}
Both produce the exact same class. The second version is way nicer for DTO-style classes.
Any modifier works — public, private, protected, readonly, or combinations:
class Account {
constructor(
public readonly id: number,
private balance: number,
protected ownerId: number,
) {}
}
Mixing parameter properties with regular params
We can mix freely — params with modifiers become fields, params without modifiers stay as plain locals.
class Order {
constructor(
public id: number, // becomes field
items: string[], // just a local
) {
console.log(items.length); // use locally, then it's gone
}
}
Interview gotchas
- Static
this: inside a static method,thisrefers to the CLASS, not an instance. Useful for static factories that need to be inheritable.
class Base {
static create<T extends typeof Base>(this: T): InstanceType<T> {
return new this() as InstanceType<T>;
}
}
class Child extends Base {}
const c = Child.create(); // c: Child
-
Parameter properties don’t work with destructuring —
constructor(public { a, b }: { a: number, b: number })is not allowed. We have to destructure inside the body. -
Static and instance with the same name are allowed — they live in different scopes. Confusing but legal.