Question
In TypeScript, using the const keyword directly on a class property causes a compiler error:
class Example {
const MY_CONSTANT = 10;
}
The error is:
A class member cannot have the 'const' keyword.
I want a clear way to express that a class property should not be changed after it is declared, and I want the compiler or IDE to report an error if I try to reassign it.
At the moment, I am using a getter like this:
get MY_CONSTANT(): number {
return 10;
}
Is there a better way to implement class constants in TypeScript, especially in newer versions such as TypeScript 2.x and later?
Short Answer
By the end of this page, you will understand why const cannot be used for class members in TypeScript, and how to model class constants correctly using readonly and static readonly. You will also learn when to use a getter, when to use an instance property, and when to use a class-level constant.
Concept
In TypeScript, const is for variables, not class members. That is why this is valid:
const MAX_RETRIES = 3;
but this is not:
class Config {
const MAX_RETRIES = 3;
}
Class members belong to an object instance or to the class itself, and TypeScript uses different keywords to control whether they can be reassigned.
The main tool for this is readonly.
class User {
readonly id: number;
constructor(id: number) {
this.id = id;
}
}
A readonly property can be assigned:
- where it is declared, or
- inside the constructor of the same class
After that, TypeScript will report an error if you try to change it.
If the value should belong to the rather than each instance, use :
Mental Model
Think of const, readonly, and static readonly as labels for different kinds of storage:
const= a sealed box sitting on a tablereadonly= a box attached to each object, sealed after setupstatic readonly= one sealed box attached to the class itself, shared by all objects
If every object should have its own unchangeable value, use readonly.
If the value is shared and should act like a constant for the whole class, use static readonly.
A getter is like asking a receptionist for the value every time. That works, but if the value is truly just a fixed constant, static readonly is usually simpler and clearer.
Syntax and Examples
Core syntax
1. readonly instance property
class User {
readonly role: string = "member";
}
This means each User instance has a role property that cannot be reassigned after initialization.
2. readonly assigned in constructor
class User {
readonly id: number;
constructor(id: number) {
this.id = id;
}
}
This is common when the value is only known when the object is created.
3. static readonly class constant
class MathConstants {
static readonly = ;
}
.(.);
Step by Step Execution
Consider this example:
class ServerConfig {
static readonly DEFAULT_PORT = 3000;
readonly host: string;
constructor(host: string) {
this.host = host;
}
}
const config = new ServerConfig("localhost");
console.log(ServerConfig.DEFAULT_PORT);
console.log(config.host);
// config.host = "example.com"; // Error
// ServerConfig.DEFAULT_PORT = 8080; // Error
Step by step
- The class
ServerConfigis declared. static readonly DEFAULT_PORT = 3000creates a class-level value.- You access it as
ServerConfig.DEFAULT_PORT. - It is shared by all uses of the class.
- You access it as
readonly host: stringdeclares an instance property that cannot be reassigned after setup.
Real World Use Cases
Where this is used
Configuration values
class ApiClient {
static readonly BASE_TIMEOUT_MS = 5000;
}
Useful for fixed settings shared across all instances.
Domain identifiers
class Order {
readonly id: string;
constructor(id: string) {
this.id = id;
}
}
An order ID should not change after creation.
Status or role values
class Account {
readonly role = "admin";
}
Good when a property should be set once and then remain stable.
Shared limits and rules
class UploadRules {
static = ;
}
Real Codebase Usage
In real projects, developers usually choose one of these patterns:
1. static readonly for constants tied to a class
class CacheService {
static readonly DEFAULT_TTL_SECONDS = 60;
}
This is common when the constant is conceptually part of the class.
2. Module-level const for shared values
const DEFAULT_TTL_SECONDS = 60;
export class CacheService {
getTtl() {
return DEFAULT_TTL_SECONDS;
}
}
This is often preferred when the value does not need to be part of the class API.
3. readonly for values fixed after object creation
class Session {
constructor(public readonly token: ) {}
}
Common Mistakes
1. Trying to use const inside a class
Broken code:
class Example {
const VALUE = 10;
}
Why it fails:
constis not valid for class members.
Use this instead:
class Example {
static readonly VALUE = 10;
}
2. Using a getter for a simple fixed value
class Example {
get VALUE(): number {
return 10;
}
}
This works, but it may suggest computation or custom logic. If the value is just a constant, static readonly is usually clearer.
3. Forgetting that readonly is compile-time protection
Comparisons
| Feature | Use case | Can change later? | Belongs to |
|---|---|---|---|
const | Local or module variable | No | Current scope |
readonly | Instance property | No, after initialization | Object instance |
static readonly | Class constant | No, after initialization | Class |
get accessor | Computed or controlled property access | Depends on implementation | Object instance or prototype |
readonly vs getter
Cheat Sheet
// Instance property that cannot be reassigned
class User {
readonly id: number;
constructor(id: number) {
this.id = id;
}
}
// Class constant
class Config {
static readonly PORT = 3000;
}
// Constructor shorthand
class Session {
constructor(public readonly token: string) {}
}
// Module-level constant
const API_URL = "https://example.com";
Rules
constcannot be used on class members.- Use
readonlyfor instance properties. - Use
static readonlyfor class-level constants. - A
readonlyproperty can be assigned:
FAQ
Why can't I use const for a class property in TypeScript?
Because const is only for variables in a scope, such as local variables or module-level values. Class members use readonly and static readonly instead.
What is the TypeScript equivalent of a class constant?
Usually static readonly.
class App {
static readonly VERSION = "1.0";
}
Should I use a getter for constants?
Usually no. Use a getter when the value is computed or when access needs custom logic. For a fixed value, readonly or static readonly is clearer.
What is the difference between readonly and const?
const is for variables. readonly is for properties on objects or classes.
Can a readonly property be assigned in the constructor?
Yes. That is one of the normal ways to initialize it.
Mini Project
Description
Build a small TypeScript class that models application settings. This project demonstrates the difference between instance-level immutable properties and class-level constants. It is useful because real applications often have fixed limits, version numbers, and IDs that should not be reassigned accidentally.
Goal
Create a ThemeConfig class with both readonly and static readonly properties, then use it safely in code.
Requirements
- Create a class-level constant for the default theme name.
- Create an instance
readonlyproperty for a config ID. - Initialize the readonly instance property through the constructor.
- Create an instance of the class and log both values.
- Verify through code comments which reassignment attempts should fail.
Keep learning
Related questions
Angular formGroup Error Explained: Fixing 'Can't bind to formGroup' in Reactive Forms
Learn why Angular shows 'Can't bind to formGroup' and how to fix it by importing ReactiveFormsModule correctly.
Fix "Element implicitly has an 'any' type" in TypeScript Object Indexing
Learn why TypeScript rejects string object indexing and how to fix it with keyof, unions, and typed object keys in React.
Fix "Property has no initializer" in Angular TypeScript Components
Learn why Angular TypeScript shows "Property has no initializer" and how to fix it using defaults, optional properties, or definite assignment.