Главная / Статьи / Тихие успехи 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);

Это означает меньше переменных, подлежащих изменению, и меньше ошибок из-за ошибки «на один единицу».

Вспомогательные типы вместо дублирующихся интерфейсов

Вместо переопределения практически идентичных интерфейсов опытные разработчики на 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 берёт на себя задачу документирования вместо комментариев, и создавайте функциональность с помощью небольших составных функций, а не крупных монолитных.

Связанная литература