Как правильно объявить константы в классе TypeScript?
Правильный способ: комбинация static и readonly
В TypeScript для объявления констант внутри класса используется связка модификаторов static readonly. Это самый правильный и распространённый подход. Давайте разберём, почему это работает именно так.
Почему const не работает внутри класса?
TypeScript (как и JavaScript) запрещает использование const внутри классов. const предназначен для объявления констант на уровне переменных, а не свойств класса. Для свойств классов используются другие механизмы.
Решение: static readonly
Вот как правильно объявить константы в вашем классе:
class MathUtils {
// Статическая константа — доступна через класс
static readonly PI: number = 3.141592653589793;
static readonly G: number = 9.80665; // Ускорение свободного падения
static readonly C: number = 299792458; // Скорость света в м/с
// Обычное readonly свойство — доступно через экземпляр
readonly name: string = "Calculator";
// Можно комбинировать
static readonly E: number = Math.E;
// Статический метод, использующий константы
static calculateCircleArea(radius: number): number {
return MathUtils.PI * radius * radius;
}
}
// Использование:
console.log(MathUtils.PI); // 3.141592653589793
console.log(MathUtils.G); // 9.80665
console.log(MathUtils.C); // 299792458
console.log(MathUtils.calculateCircleArea(5)); // 78.53981633974483
// Попытка изменить вызовет ошибку компиляции:
// MathUtils.PI = 3; // Error: Cannot assign to 'PI' because it is a read-only property
Почему это работает?
static— делает свойство принадлежащим самому классу, а не его экземплярам. Вы обращаетесь к нему черезMathUtils.PI, а не черезnew MathUtils().PI.readonly— запрещает изменение значения после инициализации. Это аналогconstдля свойств класса.
Если нужен доступ и через экземпляр
Если вам критично, чтобы константа была доступна и через экземпляр класса, можно добавить геттер:
class MathUtils {
static readonly PI: number = 3.14159;
// Геттер для доступа через экземпляр
get PI(): number {
return MathUtils.PI;
}
}
const utils = new MathUtils();
console.log(utils.PI); // 3.14159 — через экземпляр
console.log(MathUtils.PI); // 3.14159 — через класс
Лучшие практики
- Используйте
static readonlyдля настоящих констант, общих для всех экземпляров. - Именуйте константы в
UPPER_CASE(общепринятое соглашение). - Для простых констант, не связанных с классом, лучше использовать
constна уровне модуля. - Если константа зависит от конфигурации, рассмотрите использование
static readonlyс инициализацией в блокеstatic.
Надеюсь, теперь стало понятнее! static readonly — это именно то, что вам нужно.
Альтернативный подход: Константы на уровне модуля
Иногда лучше вообще не помещать константы внутрь класса, а объявить их на уровне модуля. Это особенно актуально, если константы используются не только внутри класса, но и в других частях приложения.
// constants.ts
export const PI = 3.141592653589793;
export const G = 9.80665;
export const C = 299792458;
// math-utils.ts
import { PI, G, C } from './constants';
export class MathUtils {
static calculateCircleArea(radius: number): number {
return PI * radius * radius;
}
}
Плюсы этого подхода:
- Разделение ответственности — константы отдельно, логика отдельно.
- Переиспользование — константы легко импортировать в любой файл.
- Простота — не нужно заморачиваться с
static readonly. - Tree-shaking — если константа не используется, она не попадёт в финальную сборку.
Какой подход выбрать? Если константы тесно связаны с классом и используются только в его методах — смело используйте static readonly. Если же они нужны в разных местах — выносите их в отдельный модуль. Оба варианта правильные, выбирайте по ситуации.
Ответов пока нет.
Войдите чтобы оставить ответ