Avatar ·

Как пометить свойство или метод как устаревшее (deprecated) в TypeScript?

Всем привет! Я новичок в TypeScript и работаю над библиотекой для внутреннего использования. У меня есть несколько старых функций и свойств, которые я хочу постепенно выводить из использования, чтобы перейти на новый API. Я знаю, что в JSDoc есть тег `@deprecated`, который подсвечивает метод в редакторах кода, но в TypeScript я не уверен, как это сделать правильно. Вот пример моего кода: ```typescript // Старый метод, который я хочу пометить как устаревший function calculateTotal(items: number[]): number { return items.reduce((sum, item) => sum + item, 0); } // Новый метод function calculateSum(items: number[]): number { // Новая логика с дополнительными проверками if (items.length === 0) { return 0; } return items.reduce((sum, item) => sum + item, 0); } // Старый интерфейс interface UserConfig { name: string; oldEmail?: string; // Это поле больше не используется email?: string; } ``` Я хочу, чтобы при использовании `calculateTotal` или поля `oldEmail` в редакторе (VS Code) появлялось предупреждение с зачёркиванием, как это бывает при использовании устаревших методов из стандартных библиотек. Можно ли это сделать в TypeScript без написания кастомных плагинов? Если да, то как правильно аннотировать такие элементы, чтобы предупреждение было информативным и подсказывало, что использовать вместо старого метода? Заранее спасибо за помощь! <<>>

Использование декоратора @deprecated в JSDoc

Да, в TypeScript есть встроенная поддержка пометки устаревших элементов. Самый простой и распространённый способ — использовать JSDoc-аннотацию @deprecated прямо перед объявлением функции, класса, свойства или интерфейса. TypeScript понимает этот тег и автоматически генерирует предупреждения в редакторах (VS Code, WebStorm и других).

Вот как можно исправить ваш пример:

// Старый метод — помечен как устаревший
/** @deprecated Используйте calculateSum() вместо этого метода */
function calculateTotal(items: number[]): number {
    return items.reduce((sum, item) => sum + item, 0);
}

// Новый метод
function calculateSum(items: number[]): number {
    if (items.length === 0) {
        return 0;
    }
    return items.reduce((sum, item) => sum + item, 0);
}

// Старый интерфейс
interface UserConfig {
    name: string;
    /** @deprecated Поле oldEmail больше не используется. Используйте email */
    oldEmail?: string;
    email?: string;
}

Теперь, если кто-то напишет calculateTotal([1,2,3]) или config.oldEmail, редактор покажет предупреждение с зачёркиванием и текстом из аннотации.

Более строгий подход: c помощью --noUnusedLocals и --noUnusedParameters

Вы также можете комбинировать @deprecated с флагами компилятора --noUnusedLocals и --noUnusedParameters в tsconfig.json, чтобы получать ошибки, если кто-то использует устаревший код. Однако это не прямая пометка deprecated — это просто дополнительные проверки.

Использование декоратора (экспериментально)

Если вы используете экспериментальные декораторы TypeScript (включены через "experimentalDecorators": true в tsconfig), можно создать свой декоратор, который будет выбрасывать предупреждение в консоль во время выполнения. Но это сложнее и не даёт предупреждений на этапе компиляции или в редакторе.

Важные моменты

  • Информативность: Всегда указывайте в аннотации, что использовать вместо устаревшего элемента. Это помогает разработчикам быстро перейти на новый API.
  • Версии TypeScript: Поддержка @deprecated есть во всех актуальных версиях (TypeScript 2.0+).
  • Интерфейсы и типы: Аннотация работает не только для функций, но и для свойств интерфейсов, типов, классов и даже отдельных параметров функций.
  • Планирование удаления: Если вы планируете полностью удалить устаревший код в будущем, укажите версию, начиная с которой он будет удалён, например: /** @deprecated Будет удалено в v3.0. Используйте calculateSum() */.

Таким образом, @deprecated — это стандартный и рекомендуемый способ пометки устаревшего кода в TypeScript. Он не требует дополнительных плагинов и работает «из коробки» во всех современных редакторах.

<<>>

Альтернативный подход: использование @deprecated с перегрузками функций

Если вы хотите сделать пометку более наглядной и принудительно требовать перехода на новый API, можно использовать перегрузки функций. Этот метод подходит, когда старый и новый методы имеют разные сигнатуры.

// Перегрузка с пометкой deprecated
/** @deprecated Используйте calculateSum() */
function calculateTotal(items: number[]): number;

// Новая перегрузка
function calculateSum(items: number[]): number;

// Реализация
function calculateTotal(items: number[]): number {
    return items.reduce((sum, item) => sum + item, 0);
}

function calculateSum(items: number[]): number {
    if (items.length === 0) return 0;
    return items.reduce((sum, item) => sum + item, 0);
}

Теперь при вызове calculateTotal редактор покажет предупреждение, а при вызове calculateSum — нет. Это особенно полезно, если вы хотите, чтобы старый метод всё ещё работал, но его использование было явно нежелательным.

Недостаток: Этот подход требует дублирования сигнатур и может быть избыточным для простых случаев. Для большинства ситуаций достаточно обычного JSDoc-тега @deprecated.