Private readonly members
- Modifiers:
private,readonly - Allowed:
UPPER_CASE,camelCase - Leading underscore: forbidden
Why This Rule
Private readonly members are immutable internals. They can represent either constants or configuration:
- UPPER_CASE: For true constants set at compile time (
MAX_RETRIES,DEFAULT_TIMEOUT) - camelCase: For values initialized in the constructor or set once (
apiKey,userId)
When to use each:
ts
class ApiClient {
// True constant - known at compile time
private readonly MAX_RETRIES = 3; // WHY: UPPER_CASE for a true compile-time constant
// Configuration value - set in constructor
private readonly apiKey: string; // WHY: camelCase for constructor-provided readonly value
constructor(apiKey: string) {
this.apiKey = apiKey;
}
}No underscore: The private keyword already signals encapsulation. The underscore adds no value.
Why allow both formats:
Not all readonly values are constants. Some are set once during initialization and never change, but they're instance-specific configuration rather than universal constants. Using camelCase for these feels more natural than SHOUTING_CASE.
References:
✅ Good
ts
class Example {
private readonly MAX_RETRIES = 3; // WHY: UPPER_CASE for compile-time constant
private readonly maxRetries = 3; // WHY: camelCase for instance-specific readonly value
}❌ Bad
ts
class Example {
private readonly _maxRetries = 3; // WHY: leading underscore forbidden
private readonly MaxRetries = 3; // WHY: PascalCase misleading for a property
}