Головна / Статті

Оновлення кодбази React до TypeScript 6.0: що ламається спочатку

Як суворіші стандартні значення, виправлення щодо інференції методів, імпорти підшляхів #/ та типи Temporal у TypeScript 6.0 впливають на React-додаток, а також перелік кроків для безпечного оновлення.

Видавець: REACTAPP.TOP4 хв читання842 слів

Джерела: TypeScript 6.0 for React Developers: What Actually Changed

Більшість оновлень компілятора залишаються непоміченими. TypeScript 6.0 є винятком: це остання версія, створена на основі початкового компілятора JavaScript, і вона переважно призначена для підготовки кодових баз до TypeScript 7, заснованого на Go. Тому вона містить менше функцій та більше змін, які виявляють існуючі проблеми. У цьому посібнику описано, як саме вплине це на кодову базу React, та наведений чек-лист для оновлення. Щоб дізнатися, яке місце займає 6.0 у переході до нативного компілятора, дивіться роль TypeScript 6 як мосту на шляху до нативного компілятора TS 7.

Спочатку суворіші значення за замовчуванням

TypeScript 6.0 за замовчуванням увімкнуто режим суворості, використовує ES-модулі та змінив стандартну мету на es2025. Проекти, які явно встановлюють кожен параметр, не зазнають змін; проекти, що раніше покладалися на старі більш лояльні значення за замовчуванням, стикнуться з хвилею нових помилок. У коді React найчастіше постраждають старі компоненти: параметри з несуворо визначеним типом, обробники подій із неявними параметрами типу any, референи, які можуть бути null, та функція useState() без аргументу типу. Це не регресії, а давні неоднозначності, які тепер фіксуються.

Цілі es3 та es5 також вважаються застарілими, тому мінімальною версією стає es2015. Для багатьох додатків на React це майже не змінюється, оскільки Babel, SWC чи esbuild виконують опускання синтаксису, а tsc лише перевіряє типи, проте переконайтеся в цьому перед тим, як змінювати підтримку браузерів. Запустіть оновлення на окремій гілці з повним будуванням та тестами; зміна стандартних налаштувань компілятора у п’ятницю після обіду — це надійний спосіб втратити вихідні.

Однакове інференсування для функцій у стилі методів

Ще один важливий момент стосується ситуацій, коли функція вважається „чутливою до контексту“, тобто типи її параметрів мають бути визначені з контексту, перш ніж можна буде продовжити процес інференції. У версії 6.0 вираз function або скорочення методу розглядаються таким чином лише тоді, коли вони фактично використовують this. Раніше вибір синтаксису методу замість функції-стрілки міг змінити результати інференції, навіть якщо this взагалі не використовувався. Наведений нижче приклад поєднує обидва стилі:

// Before: inconsistent inference depending on syntax
const useCounter = (initial) => {
  const [count, setCount] = useState(initial);

  // this pattern used to infer differently than an arrow fn
  const increment = function () {
    setCount((c) => c + 1);
  };

  return { count, increment };
};

Раніше калебек, як-от increment, міг інферуватися по-іншому, ніж еквівалентна функція-стрілка, і в більших хуках ця різниця могла призвести до передачі слабшого типу користувачам. Тепер синтаксис, який ви обираєте для калебеків та повернутих допоміжних функцій, більше не змінює отримані типи, що усуває причину плутанини з питанням „чому цей калебек не перевіряється?“.

Більш чисте імпортування за допомогою префікса #/

Імпорти підшляхів у Node визначають приватні псевдоніми у полі imports файлу package.json, і TypeScript 6.0 підтримує там префікс #/, що відповідає кореневим псевдонімам, які зазвичай використовуються бандлерами. Оголосіть це мапування один раз:

{
  "imports": {
    "#/*": "./src/*"
  }
}

Потім компоненти імпортують з кореня проєкту, замість того щоб рахувати сегменти ../:

// No more relative path spaghetti in deeply nested components
import { useAuth } from "#/hooks/useAuth";
import { Button } from "#/components/ui/Button";

Оскільки псевдонім знаходиться у package.json, а не лише у розділі paths файлу tsconfig.json, Node та TypeScript обробляють його однаково, без додаткових плагінів. Це працює лише у режимах обробки, які читають імпорти з package.json, наприклад nodenext або bundler.

Тимчасові типи поставляються вбудовано

TypeScript 6.0 містить декларації для API Temporal, який досяг останньої стадії стандартизації TC39. Команди, які розробляють інтерфейси для планування, бронювання чи панелей керування, можуть використовувати Temporal.PlainDate або Temporal.ZonedDateTime без додаткових пакетів, замість того щоб працювати з типом Date. Однак ці типи не забезпечують підтримки на рівні виконання коду: перевірте нативну підтримку у ваших цільових браузерах та версіях Node та додайте поліфіл, якщо це необхідно.

Чи варто оновлюватися зараз?

Так, свідомо. Команда TypeScript пропонує 6.0 як стабільне оновлення, але зміни всередині справжні:

  • Перевірте файл tsconfig.json та закріпіть кожен параметр, від якого ви залежите.
  • Виправляйте нові помилки у режимі суворості у старих компонентах, замість того щоб приглушувати їх за допомогою any.
  • Переконайтеся, який інструмент виконує оновлення до меншої версії та яку цільову версію він потребує.
  • Для кодових баз із компонентами класів або сховищами, керованими класами, розгляньте можливість увімкнення noImplicitOverride, щоб для перевизначених елементів було обов’язкове використання ключового слова override.
  • Підсумок

    TypeScript 6.0 не змінить спосіб написання коду для React, але він усуне наслідки використання невизначених значень за замовчуванням. Погашення цих наслідків зараз, згідно з вашим графіком, значно дешевше, ніж робити це пізніше в році, коли також буде здійснено оновлення з версії 6 на 7, що перетворить цей крок переважно на питання продуктивності.