Головна / Статті / Тихі досягнення TypeScript 6 та звички розробників на JavaScript

Тихі досягнення TypeScript 6 та звички розробників на JavaScript

Дізнайтеся про недооцінені функції TypeScript 6, такі як пряме керування ресурсами та параметри типу const, а також про ідіоми JavaScript, від яких щодня залежать старші інженери.

1228 слів

Сучасний JavaScript та TypeScript продовжують розвиватися у способи, які значно виходять за межі заголовкових функцій та пунктів списку змін. Наразі важливими є два аспекти практики: менш помітні та менш просувані у засобах масової інформації додатки в TypeScript 6, а також повсякденні ідіоми JavaScript, які відрізняють запити високого рівня від просто функціонального коду. Обидва аспекти стосуються однієї й тієї самої дисципліни — достатнього розуміння інструментів, щоб обирати правильний замість знайомого. У цій статті розглядаються обидва аспекти: спочатку те, що було додано в TypeScript 6 майже непомітно, а потім шаблони JavaScript, до яких звертаються досвідчені інженери як до стандартних рішень.

Непомітні оновлення TypeScript 6, які варто прийняти

Більшість матеріалів про TypeScript 6 обмежуються тим, що строгий режим та ES2025 тепер є стандартними налаштуваннями. Це справді важлива зміна, але вона затьмарює низку менших доповнень, які тихо усувають давно існуючі обхідні шляхи. Якщо ви читатимете лише заголовки tsconfig-default, ви пропустите більш корисну частину оновлення.

Очищення, про яке не потрібно пам’ятати

Поширеною причиною помилок є забування закрити з’єднання до бази даних чи видалити слухач. TypeScript 6 вирішує цю проблему завдяки чіткому керуванню ресурсами, дозволяючи позначити значення так, щоб воно автоматично було очищене після виходу з області видимості.

function readUserSession() {
  using session = openSession(); // auto-disposed at scope end
  const user = session.getUser();
  return user.name;
} // session.dispose() called automatically here

Це усуває потребу в блоках try/finally, єдиною функцією яких було забезпечення очищення. Додавання синтаксису є незначним, але підвищення надійності є значним для всього, що пов’язано з файлами, сокетами чи відкритими з’єднаннями.

Літеральні типи без постійного використання as const

Раніше, щоб зберегти літеральні типи у генеричних функціях, доводилося постійно використовувати as const у всьому коді. TypeScript 6 вводить параметри типу const, які автоматично зберігають інференцію літеральних типів.

function createConfig<const T extends Record<string, unknown>>(config: T) {
  return config;
}

const config = createConfig({
  env: "production",
  features: ["auth", "billing"],
});
// config.env is "production", not string
// config.features is readonly ["auth", "billing"], not string[]

Якщо ви створюєте клієнтів API з типизацією або пишете функції створення дій у Redux, це значно скорочує кількість шаблонного коду з as const, який інакше був би необхідний.

Правильне звуження типів усередині switch (true)

Ще одне корисне вдосконалення: тепер можливо правильно звужувати типи усередині оператора switch (true), що раніше змушувало використовувати вкладені ланцюги if/else, щоб компілятор зрозумів ваші типи.

function area(shape: Shape): number {
  switch (true) {
    case shape.kind === "circle":
      return Math.PI * shape.radius ** 2; // narrowed to Circle
    case shape.kind === "rectangle":
      return shape.width * shape.height; // narrowed to Rectangle
  }
}

Завдяки цій зміні вам більше не доводиться відмовлятися від switch, щоб зберегти цілісність обмеження типу.

Temporal отримує першокласні типи

TypeScript 6 також постачає вбудовані типи для API Temporal, тож вам більше не доводиться боротися з Date та його особливостями часових зон за допомогою ручних підтверджень типу.

const meetingStart = Temporal.Instant.from("2026-04-06T10:00:00Z");
const localTime = meetingStart.toZonedDateTimeISO("America/Toronto");

Імпорти підшляхів, які дійсно працюють

Також була виправлена ще одна, хоча й менш значна, але дійсно дратівлива проблема: внутрішні імпорти підшляхів тепер правильно працюють, без необхідності використання довгої ланцюга сегментів відносних шляхів.

import { User } from "#/models/user.js";
// instead of ../../../models/user.js 🙃

Менеджер проекту TypeScript Даніель Розенвассер описав TS6 як свідомий місток до майбутнього TypeScript 7, заснованого на Go, що свідчить про те, що це не експериментальні додаткові функції — вони призначені залишитися. Якщо ваша команда працює з повноцінним кодовим базисом на JavaScript, React чи Next.js, впровадження цих практик зараз має допомогти уникнути несподіванок під час появи TypeScript 7. Загалом, TypeScript 6 — це не лише нові стандартні налаштування компілятора; він також забезпечує краще керування ресурсами, точніше визначення типів та меншу кількість ручних рішень. Використання параметрів типу using та const у вашому наступному pull request може змусити вас замислитися, як ви справлялися без них.

Практики JavaScript, які відрізняють досвідчених програмістів від інших

Знання новіших можливостей TypeScript — це лише половина картини. Інша половина полягає у тому, як щодня пишеться сам JavaScript. Коли запит на зміни від старшого інженера виглядає чистіше, ніж у всіх інших, це рідко пов’язано з кмітливістю — це результат послідовного застосування певних звичок без вагань.

Необов’язкове ланцюгування та об’єднання значень null

Замість ланцюгів на кшталт user && user.profile && user.profile.name старший рівень кодування використовує необов’язкове ланцюгування у поєднанні з об’єднанням значень null.

const displayName = user?.profile?.name ?? 'Guest';

Це лаконічно, захищає від відсутніх значень та не призводить до проблем під час рефакторингу навколишнього коду.

Розбирання елементів із значеннями за замовчуванням

Розбирання параметрів, відповідей API та аргументів функцій із розумними значеннями за замовчуванням є природним навиком на цьому рівні.

function createUser({ name, role = 'member', isActive = true }) {
  return { name, role, isActive };
}

Це дозволяє безпосередньо у сигнатурі функції описати очікувану структуру даних.

Async/Await замість ланцюгових обіцянок

Використання ланцюга .then().then().catch() все ще працює, але не ефективно при зростанні складності логіки. Порівняйте це з версією на async/await:

async function fetchOrders(userId) {
  try {
    const res = await fetch(`/api/orders/${userId}`);
    if (!res.ok) throw new Error('Failed to fetch orders');
    return await res.json();
  } catch (err) {
    console.error('Order fetch failed:', err);
    throw err;
  }
}

Результат читається зверху вниз, що полегшує дебаггінг та тестування.

Методи масивів замість ручних циклів

Використання методів map, filter, reduce та find замінює більшість власноруч написаних циклів for.

const activeAdmins = users
  .filter((u) => u.isActive && u.role === 'admin')
  .map((u) => u.email);

Це означає меншу кількість змінних та менше помилок через неправильне врахування значення 1.

Функціональні типи замість дубльованих інтерфейсів

Замість того, щоб переопределяти майже ідентичні інтерфейси, досвідчені розробники TypeScript використовують утилітні типи, такі як Partial, Pick та Omit.

type UserFormInput = Pick<User, 'name' | 'email'> & Partial<Pick<User, 'phone'>>;

Це забезпечує єдине джерело істини, тож зміни схеми вимагають оновлень у меншій кількості місць.

Хуки та композиція в React

Спеціалізовані хуки, які витягують та інкапсулюють логіку, постійно зустрічаються у зрілих кодових базах React.

function useDebouncedValue(value, delay = 300) {
  const [debounced, setDebounced] = useState(value);

  useEffect(() => {
    const timer = setTimeout(() => setDebounced(value), delay);
    return () => clearTimeout(timer);
  }, [value, delay]);

  return debounced;
}

Такий хук дозволяє повторно використовувати основну логіку та тестувати її незалежно від конкретного компонента.

Структуроване управління станом

Для управління станом багато досвідчених команд віддають перевагу компонентам Redux Toolkit перед власноруч написаними редюсерами, створеними за допомогою операторів switch, оскільки RTK скорочує кількість шаблонного коду та забезпечує імутабельність завдяки Immer.

Як відомо, Дуглас Крокфорд зазначав, що JavaScript складається з „хороших та поганих елементів“ — саме та гнучкість, яка робить цю мову потужною, водночас спричиняє плутанину. Знання того, на які елементи слід покладатися, — ось що відрізняє впевнених інженерів від тих, хто ще шукає свою нішу.

Короткий набір принципів поєднує все це воєдино: надавайте перевагу читабельності перед винахідливістю, нехай система типів TypeScript бере на себе обов’язки документування замість коментарів, а функціональність будується за допомогою невеликих складених функцій, а не великих монолітних.

Пов’язана література