All streams
Search
Write a publication
Pull to refresh
28
0
Andrei Chmelev @andry36

Senior Full Stack Engineer / Tech Lead

Send message

Действительно, использование кортежа отлично упрощает логику, ведь тогда не нужно явно вычитать глубину. Хороший паттерн - компактнее и понятнее.
Поменял пример в статье.
Спасибо за идею!

Спасибо за детальный фидбек!👍
Я понимаю, что некоторые фичи TypeScript (та же вариативность кортежей с TS 4.0) давно не в статусе горячих новостей. Однако статья и не претендовала на роль "свежайшей сводки" - её идея в том, чтобы дать обзорный срез тем, кто ещё не имел возможности глубоко разобраться в type-level приёмах.

Что касается ссылок на конкретные версии и документацию - да, при желании можно было бы детальнее расписать, в каких именно релизах появились те или иные возможности, или дать ссылки на соответствующие pull request’ы и блоги TypeScript. Но основная цель статьи - поделиться практическими кейсами и паттернами, а не быть исчерпывающей технической справкой.

В любом случае, замечания учту. Поправлю формулировки на которые вы указали, добавлю несколько уточнений и ссылок, чтобы новички или те, кто захочет глубже копнуть, могли быстро сориентироваться в официальной документации.
Спасибо, что обратили внимание на эти моменты!

Зацепление может возникнуть, если перегибать с абстракциями и усложнять, где это не требуется. Но в этом и суть type-level подхода - он добавляет строгую типизацию там, где она реально нужна (например, в сложных API или конфигурациях), а не в простых сценариях. Для обычных действий никто не мешает использовать простые массивы или объекты. Главное - уметь вовремя остановиться и не применять тяжелую артиллерию к каждому кейсу 🙂

ИМХО, удачный пример использования type-level подхода — это работа с Redux Toolkit. Когда вы описываете endpoints, на основании их описания можно автоматически получить готовые типизированные хуки с различным функционалом (например, лениво мутирующие, простые GET-запросы и т.д.). Это помогает избавиться от рутины и избежать ошибок, сохраняя код чистым и понятным.

import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';

// Описание API
export const api = createApi({
  reducerPath: 'api',
  baseQuery: fetchBaseQuery({ baseUrl: '/api' }),
  endpoints: (builder) => ({
    createUser: builder.mutation<{ success: boolean }, { name: string; age: number }>({
      query: (newUser) => ({
        url: 'user',
        method: 'POST',
        body: newUser,
      }),
    }),
  }),
});

// тут все типизировано :)
export const {
  useCreateUserMutation, // Обычный хук
  useLazyCreateUserMutation, // Ленивый хук
} = api;

function UserForm() {
  const [createUser, { isLoading, isSuccess, isError }] = useCreateUserMutation();
  const [triggerLazyCreateUser, { isLoading: isLazyLoading }] = useLazyCreateUserMutation();

  const handleCreateUser = () => {
    createUser({ name: 'John Doe', age: 30 });
  };

  const handleLazyCreateUser = () => {
    triggerLazyCreateUser({ name: 'Jane Doe', age: 25 });
  };

  return (
    <div>
      {/* ... */}
    </div>
  );
}

Отличный работа!👍 Понравилась реализация диагностики дублирующихся и пересекающихся индексов. Это реальная боль в крупных проектах, и автоматизация таких проверок - прямое спасение для DBA. Интересно, планируется ли интеграция pg-index-health с популярными CI/CD инструментами вроде GitHub Actions или GitLab CI?
Спасибо за подробное описание и open source!

Теперь осталось научиться звонить с холодильника, и я полностью готов к цифровому детоксу! :)

Спасибо за статью!
Пробовали ли вы настраивать youtubeUnblock с использованием IPv6?

Интересная статья! Возник вопрос: насколько изменения в экспрессии генов, например Csmd1 в таницитах, обратимы? Есть ли исследования, где тестировались способы восстановления их функций через диету, фармакологию или другой подход?

Спасибо за мнение!
Логику в типах стоит применять по необходимости, чтобы не превратить код в хаос). Это дополнительный инструмент, а не замена обычного кода.

Спасибо за мнение! Архитектура ОС действительно лежит в основе параллелизма. Но для веб-разработчиков важно сначала освоить практическое применение асинхронности в рамках Event Loop и API языка. ИМХО углубление в базовые механизмы хоть и полезно, но не всегда обязательно для начального понимания.

Рад, что материал оказался полезным вне зависимости от стека :)

Спасибо за ваши мысли! :)
Наверное, важно упоминуть, что исторически браузерный JavaScript создавался как событийно-ориентированный язык, чтобы пользовательский интерфейс не блокировался во время выполнения кода. Это обусловлено однопоточностью: если бы код мог синхронно ждать результат какого-нибудь действия (например, сетевого запроса), вся страница «зависала» бы до получения ответа, и взаимодействие с ней было бы невозможным. Асинхронная модель здесь не просто дань моде, а способ обеспечить отзывчивость и избежать блокировок.

Почему с геймпадом можно обойтись опросом "на месте", а с клавиатурой и мышью - нет? Геймпад API добавляли позднее, учитывая особенности игр (где логика кадра и прямой опрос железа - обычная практика). Клавиатура и мышь в браузере изначально пошли другим путём - событием: нажатие, отпускание, движение. Это наследие DOM-модели и всего, что в ней связано с обработкой пользовательских действий, фокусом и безопасностью.

Наконец, async/await хотя и является синтаксическим сахаром над промисами, всё-таки упрощает написание асинхронного кода. Важно понимать, что асинхронность в JS востребована не только при обработке событий ввода, но и при работе с сетью, файлами, базами данных. В условиях одного потока это помогает не подвешивать UI, пока мы ждём ответ от сервера или читаем данные из indexDB.

Я согласен, что браузерные API не идеальны, и в некоторых местах они выглядят как исторический атавизм, но ИМХО менять их радикально уже поздно: слишком много кода написано в расчёте на текущий подход. В итоге мы имеем модель, которая может показаться избыточно сложной, однако она решает фундаментальную проблему блокировок и сохраняет гибкость для дальнейшего развития платформы.

Вложенность (callback hell). Много уровней колбэков, код уезжает вправо и становится нечитабельным.

Сложная обработка ошибок. Приходится вручную передавать и обрабатывать ошибки в каждом колбэке.

Трудности с управлением потоком. Параллельные и последовательные задачи требуют дополнительных ухищрений (счётчики, ручная синхронизация и т. д.).

Невозможность вернуть значение "наверх". Результат появляется только внутри колбэка, что сбивает с толку и усложняет структуру программы.

Наиболее близкий к классическому sleep способ в JavaScript - это промис с setTimeout, который удобно использовать вместе с async/await. Например:

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function doSomething() {
  console.log('Начинаем...');
  await sleep(2000); // спим 2 секунды
  console.log('Продолжаем!');
}

Такой подход позволяет писать код последовательно (как будто действительно есть sleep), не разрывая логику на несколько колбэков. Синтаксически это самое простое решение, поскольку "настоящей" блокирующей паузы (как в других языках) в JavaScript нет - в нём однопоточная модель с циклом событий, и принудительная остановка потока в целом не предусмотрена.

Спасибо, рад, что статья оказалась полезной!

Спасибо за обратную связь!
Согласен, что Promise.allSettled очень удобен для обработки ошибок, когда важны результаты всех запросов.

Спасибо за ваш опыт! Полностью согласен, что лучше вводить асинхронность постепенно и "показывать магию" в небольших примерах, чтобы студенты сами прочувствовали, как всё работает. Так они осознают, почему колбэки неудобны, как промисы упрощают жизнь, и наконец приходят к async/await с чётким пониманием "что" и "почему".

Спасибо за ваш комментарий! Я согласен, что документация - важная часть изучения любой технологии. Однако, на мой взгляд, простые эксперименты (в том числе с setTimeout) тоже дают очень ценное понимание того, как работает асинхронность. Документация помогает увидеть "официальную" картину, а игры с кодом помогают прочувствовать все механизмы на практике и лучше понять, какие возникают проблемы и почему. Так что, как часто бывает, лучший путь - это сочетание теории и практических экспериментов.

Вы абсолютно правы, термин "fulfilled" действительно точнее описывает успешное завершение промиса. Спасибо за уточнение! Исправил этот момент!

Спасибо за добрые слова! Рад, что статья оказалась полезной.

Здравствуйте! Если вам показалось, что в статье что-то лишнее или недостаточно полезное, буду рад узнать, что именно, чтобы улучшить материал. Конструктивная критика всегда приветствуется!

Information

Rating
Does not participate
Registered
Activity

Specialization

Fullstack Developer, Software Architect
Lead
JavaScript
Node.js
React
TypeScript
Vue.js
Web development
NestJS
React Native
Java
Docker