Предупреждение об экспериментальных декораторах в TypeScript
Причина предупреждения и решение
Вы столкнулись с типичной ситуацией. Предупреждение возникает, потому что декораторы в TypeScript всё ещё считаются экспериментальной функцией. Хотя они широко используются в фреймворках (Angular, NestJS, TypeORM), стандарт ECMAScript до сих пор не утвердил их окончательную спецификацию. TypeScript реализовал их раньше стандарта, но с пометкой "экспериментально".
Чтобы убрать предупреждение, нужно правильно настроить tsconfig.json. Вот минимальная рабочая конфигурация:
{
"compilerOptions": {
"target": "ES6",
"experimentalDecorators": true,
"emitDecoratorMetadata": true, // опционально, для получения метаданных
"module": "commonjs",
"outDir": "./dist",
"rootDir": "./src",
"strict": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
Проверка корректности
Убедитесь, что:
- Файл
tsconfig.jsonнаходится в корневой папке проекта (где лежит package.json). - В VSCode используется верный TypeScript — не встроенный, а из
node_modules(см. настройкуtypescript.tsdk). - После добавления опции перезапустите компиляцию:
npx tsc --watchили через Ctrl+Shift+B.
Почему декораторы экспериментальные?
Декораторы — это предложение для JavaScript (stage 2 на момент написания). TypeScript добавил их раньше, но синтаксис может измениться. Пример различий:
- Текущий TypeScript-синтаксис (экспериментальный):
@logнад методом. - Будущий стандарт может использовать другой подход (например, декораторы как функции высшего порядка).
Поэтому Microsoft честно предупреждает: "используйте на свой страх и риск, API может поменяться". Однако для современных проектов это безопасно — Angular и NestJS полностью на них завязаны, и они вряд ли сломают обратную совместимость.
Полный пример рабочего кода
После настройки tsconfig ваш код будет компилироваться без предупреждений. Вот улучшенная версия декоратора с поддержкой асинхронных методов:
function log(
target: any,
propertyKey: string,
descriptor: PropertyDescriptor
) {
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
console.log(`[LOG] Вызван ${propertyKey} с аргументами:`, args);
const start = Date.now();
const result = originalMethod.apply(this, args);
const duration = Date.now() - start;
console.log(`[LOG] ${propertyKey} завершён за ${duration}мс, результат:`, result);
return result;
};
return descriptor;
}
class Calculator {
@log
add(a: number, b: number): number {
return a + b;
}
@log
multiply(a: number, b: number): number {
return a * b;
}
}
const calc = new Calculator();
console.log(calc.add(2, 3)); // Логи: вызов, завершение, результат 5
console.log(calc.multiply(4, 5)); // Логи: вызов, завершение, результат 20
Альтернатива без декораторов
Если вы не хотите использовать экспериментальную функциональность, можно обойтись функциями-обёртками:
function withLogging(method: Function) {
return function (...args: any[]) {
console.log(`Вызван метод с аргументами:`, args);
return method(...args);
};
}
class Calculator {
add = withLogging(function(a: number, b: number) {
return a + b;
});
}
const calc = new Calculator();
calc.add(2, 3); // Работает без предупреждений
Но этот подход менее удобен для множества методов.
Рекомендация
Используйте декораторы смело — они стабильны в TypeScript уже много лет. Просто добавьте "experimentalDecorators": true в tsconfig.json, и всё будет работать. Если проект строго требует "чистого" ES-стандарта, подождите окончательной спецификации (ожидается в ES2024+).
Дополнительный подход: настройка через jsconfig.json для VSCode
Если вы используете Visual Studio Code для JavaScript-проекта (не TypeScript), настройка делается аналогично через файл jsconfig.json. Создайте его в корне проекта:
{
"compilerOptions": {
"experimentalDecorators": true,
"target": "ES6"
},
"include": ["src/**/*"]
}
После этого VSCode перестанет показывать предупреждение во время редактирования.
Почему предупреждение может оставаться
Иногда VSCode использует свою встроенную версию TypeScript, которая не читает tsconfig. Чтобы это исправить:
- Нажмите
Ctrl+Shift+P→TypeScript: Select TypeScript Version. - Выберите
Use Workspace Version(версию изnode_modules).
Если вы используете ts-node для запуска, добавьте флаг в package.json:
"scripts": {
"start": "ts-node --experimentalDecorators src/index.ts"
}
Когда стоит избегать декораторов
Если ваш проект — библиотека с открытым исходным кодом, которую будут использовать другие разработчики, лучше избегать экспериментальных декораторов. Вместо этого используйте паттерн "фабрика функций" или HOF (higher-order functions). Это гарантирует совместимость с любыми версиями TypeScript и JavaScript.
Пример для библиотеки:
// Вместо @log используем функцию-декоратор
function withLogging(fn: T): T {
return ((...args: any[]) => {
console.log(`Вызов функции: ${fn.name}`);
return fn(...args);
}) as T;
}
const add = withLogging((a: number, b: number) => a + b);
Такой код работает везде без предупреждений и не требует экспериментальных опций.