Переписувати все одразу ризиковано й довго. TypeScript дозволяє змішувати JavaScript і TypeScript в одному проєкті й переходити по файлу.
Крок 1 - tsconfig.json з дозволом JavaScript:
{
"compilerOptions": {
"allowJs": true,
"checkJs": false,
"strict": false,
"noEmit": true
},
"include": ["resources/js"]
}
allowJs-.js-файли входять у проєкт: TypeScript-файли можуть їх імпортувати, редактор дає підказки;checkJs- перевіряти й.js-файли. Можна вмикати точково - коментарем// @ts-checkна початку окремого файлу.
Крок 2 - типи в JavaScript через JSDoc (без перейменування файлів):
// @ts-check
/**
* @param {number} amount
* @param {'UAH' | 'USD'} currency
* @returns {string}
*/
export function formatPrice(amount, currency) { /* ... */ }
/** @typedef {{ id: number, name: string }} User */
Крок 3 - перейменування файлів у .ts - починаючи з «листових» модулів без залежностей (утиліти, константи, API-клієнт), потім угору до компонентів.
Крок 4 - посилення строгості: спершу noImplicitAny, потім strictNullChecks, наприкінці повний strict.
Що змінилося в TypeScript 7 для JavaScript-файлів. Аналіз JSDoc став ближчим до звичайного TypeScript, частина старих конструкцій більше не розпізнається:
@enumне має особливого значення - потрібен@typedefнад(typeof Obj)[keyof typeof Obj];- синтаксис Closure (
function(string): void) замінюється на(s: string) => void; - одинокий
?як тип і постфіксний!не підтримуються; @classне робить функцію конструктором - потрібенclass.
Тому JSDoc у старих проєктах після оновлення може дати нові помилки.
Практичні поради:
- не змінювати поведінку разом з типами - міграція окремими комітами, без рефакторингу логіки;
anyдозволений як тимчасовий, але з позначкою (// TODO: тип) - і лінтер, що рахує їх кількість;- типи для відповідей API - одне з перших, що варто додати: вони дають найбільше користі;
@ts-expect-errorкраще за@ts-ignore- він сам повідомить, коли помилку виправлено і коментар можна прибрати.