This TypeScript error means const can’t be used on class members; swap to readonly or move the const outside the class.
You’ll see this message while building an Angular app that uses TypeScript. It usually shows up right after you add a “constant” inside a class and the build stops cold.
The good news is that the fix is simple once you know what TypeScript allows inside a class, and what it only allows at the file level. It’s a quick, clean swap. That’s it, done.
It often comes from a copy paste snippet that uses const at top level then gets dropped straight into a class.
Once you spot the pattern, you can fix it in minutes and stop the error from popping up again in the next file you touch.
Why This Error Shows Up In Angular
Angular files are TypeScript files. When TypeScript compiles a class, it expects members like properties, methods, getters, and setters. The const keyword isn’t a class-member modifier, so the compiler rejects it.
You’ll often trigger the error in one of these situations.
- Declaring a const field — You write
const apiUrl = '...'inside a class body. - Creating a const object — You try
const httpOptions = { ... }as a class property. - Using const for a method — You attempt something like
const loadData() { ... }.
TypeScript reports this as error TS1248. Angular just surfaces that compiler message during the build.
Spot The Exact Line Fast
The compiler points to a line number. Open that file and check what sits directly above the error. In many cases you’ll see const right inside the class body, not inside a method.
// ❌ This triggers TS1248
export class DemoComponent {
const label = 'Save';
}
Rewrite it as a property. If the value should never be replaced, add readonly.
// ✅ Valid in a class
export class DemoComponent {
readonly label = 'Save';
}
If you only needed a temporary variable for a calculation, move it into the method where it belongs.
export class DemoComponent {
buildLabel(userName: string) {
const label = `Save ${userName}`;
return label;
}
}
What Const Means In TypeScript
In TypeScript (and JavaScript), const declares a block-scoped variable. It works for variables inside a file, inside a function, or inside a block like an if statement.
Classes are different. Inside a class body, you declare members. A property can be initialized, but it is not declared with const or let.
If your goal is “don’t let anything reassign this value,” TypeScript gives you better tools that fit class design.
Const Does Not Mean Fully Immutable
Const stops reassignment of the variable binding. It does not lock down the value itself. That matters for objects and arrays.
const headers = { accept: 'application/json' };
// headers = {} // ❌ blocked
headers.accept = '*/*' // ✅ still allowed
This is one reason const isn’t a perfect stand-in for a class constant. Inside a class, you usually care about the public shape and whether callers can replace a value.
Class Members Use Modifiers, Not Declarations
Inside a class, you don’t write let or const. You either declare a member and give it an initializer, or you type it and fill it later.
- Property with initializer —
readonly timeoutMs = 5000; - Typed property set later —
token!: string;and assign in a method. - Property set in constructor —
constructor(readonly id: string) {}
Once you follow those rules, the compiler error disappears and the code reads like TypeScript instead of file-scope JavaScript dropped into a class.
| What You Wrote | Why It Fails | What To Use |
|---|---|---|
const apiUrl = '...' |
const isn’t valid on a class member |
readonly apiUrl = '...' |
const headers = { ... } |
Class members aren’t declared with const |
readonly headers = { ... } |
const load() { } |
Methods don’t take const |
load() { } or a property arrow |
Angular A Class Member Cannot Have The Const Keyword Fixes That Stick
Pick the fix that matches what you were trying to store: a single value, a shared constant, or a helper object. The goal is the same: keep the value stable, without using const on a class member.
Fix 1 Use Readonly For An Instance Property
If each instance of the class can carry its own value, declare a property and mark it readonly. This blocks reassignment after initialization.
export class UserService {
readonly apiUrl = 'https://api.example.com';
}
This pattern works well in components, services, and guards when the value does not need to change for the life of the instance.
Fix 2 Use Static Readonly For A Shared Constant
If you want one shared value for the class, use a static property and make it readonly. This gives you a single place to reference it without creating an instance.
export class ApiConfig {
static readonly baseUrl = 'https://api.example.com';
}
Then read it like ApiConfig.baseUrl. This is close to the mental model of a “class constant” from other languages.
Fix 3 Move Const To File Scope
If you truly want a file-level constant, declare it outside the class. This keeps const in the place where TypeScript expects it.
const DEFAULT_PAGE_SIZE = 25;
export class ListComponent {
pageSize = DEFAULT_PAGE_SIZE;
}
This is a clean option when the value is only used in that file. It also keeps the class body lean.
Fix 4 Use A Getter When You Need Late Initialization
Sometimes you want a value that looks constant to callers, yet it is computed from injected services or set after construction. A getter can expose a read-only view.
export class AuthService {
private _token = '';
setToken(token: string) {
this._token = token;
}
get token(): string {
return this._token;
}
}
Callers can read token, but they can’t assign to it directly.
Fix 5 Use As Const Or An Enum For Named Values
When the real need is a set of named choices, you can lean on TypeScript’s type system instead of a single constant property.
as const keeps literal values narrow, which helps when you want a union like 'draft' | 'published' without hand-writing the type.
export const POST_STATUS = ['draft', 'published', 'archived'] as const;
export type PostStatus = typeof POST_STATUS[number];
If you prefer named members, an enum can work too. Keep it small and clear, and keep it at file scope.
export enum Role {
Admin = 'admin',
Editor = 'editor',
Viewer = 'viewer'
}
Pick Public Or Private On Purpose
Angular templates can only see what’s public on the component instance. If a constant is only used inside the class, mark it private readonly.
If the template needs it, keep it readonly and public. That makes intent obvious and stops accidental reassignment from your own code.
- Template uses it —
readonly label = 'Save'; - Class only uses it —
private readonly label = 'Save';
Common Angular Patterns That Trigger The Error
Most “angular a class member cannot have the const keyword” reports come from a small set of patterns. Here are the usual ones, with fixes you can paste in.
Declaring An Array Or Map For Reuse
It’s common to stash lookup lists in a component. Don’t write const items: string[] = [] in the class body. Use a property instead.
- Use readonly when you don’t reassign — Declare
readonly items: string[] = [];and push into it if you must. - Use a plain property when you will replace — Declare
items: string[] = [];when you plan to set a new array.
export class TagsComponent {
readonly tags: string[] = ['new', 'sale', 'staff'];
}
Storing Http Options On A Service
Many code samples create request options like headers. If you put those in a service as const, the compiler throws. Use private readonly so callers can’t touch it.
import { HttpHeaders } from '@angular/common/http';
export class DataService {
private readonly jsonHeaders = new HttpHeaders({
'Content-Type': 'application/json'
});
}
That keeps the property stable and keeps it out of the public surface of the class.
Using Static Values In A Template
A static property is not read from the instance in a template. If you want a template to reference a shared constant, expose it through an instance property.
export class Plan {
static readonly free = 'free';
static readonly pro = 'pro';
}
export class BillingComponent {
readonly Plan = Plan;
}
Then the template can read Plan.free and Plan.pro through that exposed reference.
Trying To “Const” A Method
If you tried to write a method with const, delete the keyword. Methods are already part of the class shape.
- Write a normal method — Use
loadData() { ... }for most cases. - Use an arrow property when you need this binding — Use
readonly loadData = () => { ... }when passing the function around.
export class PanelComponent {
readonly close = () => {
// ...
};
}
Readonly Is Not The Same As Frozen
Readonly blocks reassignment of the property, not mutation of the thing it points to. That trips people up with objects and arrays.
If you write readonly settings = { theme: 'dark' }, you can’t reassign settings, but you still can change settings.theme unless you also guard against mutation.
When You Want A Truly Fixed Object
When you need to prevent accidental mutation, pick a pattern that matches your needs.
Readonly Arrays And Tuples In Practice
If you want TypeScript to block array writes, type it as a readonly array. This keeps you from calling push, splice, and other mutating methods.
const ROUTES: readonly string[] = ['/home', '/settings'];
When you need both safety and convenient edits, keep an immutable default and clone it when building a new value.
const DEFAULT_FILTERS = Object.freeze({ q: '', page: 1 });
export class SearchComponent {
filters = { ...DEFAULT_FILTERS };
}
- Use a readonly type — Type the value as
Readonlyorreadonlyarrays to block writes at compile time. - Freeze at runtime — Use
Object.freeze()for runtime protection, and treat it as immutable data. - Copy before edit — When you must change data, create a new object with spread syntax and assign it to a non-readonly property.
type Settings = { theme: string; pageSize: number };
const DEFAULT_SETTINGS: Readonly = Object.freeze({
theme: 'dark',
pageSize: 25
});
Checklist To Clear The Error Fast
If the build fails and you just want it green, run this quick pass through the file that threw TS1248.
- Search for const inside class bodies — If you see
constbetweenclass X {and its closing brace, remove it. - Decide where the value belongs — File-level constants stay outside the class. Per-instance values become properties.
- Choose readonly when reassignment is a bug — Add
readonlyfor values you never want to replace. - Use static readonly for shared constants — Put truly shared constants on the class, not on each instance.
- Rebuild and re-run tests — Confirm the fix and scan for any follow-on type errors.
If the same message repeats across several files, use your editor’s search to look for const right after a newline and two spaces of indentation inside classes. That pattern often catches the stray lines fast.
After the change, stop and start the Angular dev server so you’re compiling fresh. If you use a build cache, clear it once and run a clean build.
Once you swap the invalid const usage, the message “angular a class member cannot have the const keyword” disappears and your Angular build should pass again.
