tgindex
Frontend Alliance | Автушенко Андрей

Frontend Alliance | Автушенко Андрей

Статистика

Меня зовут Автушенко Андрей. Здесь рассказываю про карьеру во frontend-разработке, менторство и личную жизнь Менторство - frontend-alliance.ru Отзывы - https://t.me/palaxius_reviews Написать лично - @palaxius YouTube: youtube.com/@FrontendAlliance

Последний пост
6 авг.
Последнее чтение
14 авг.
Постов за неделю
0
Всего постов
21
Тип
открытый
Язык
русский
Категория
Карьера
В каталоге с
14 авг.
Подписчики
1 930
−3 за 3 дн.
Сутки
−1
−0,05%
Неделя
 
Месяц
 
Просмотров на пост
1 525
21 постов
Вовлечённость
79,0%
к подписчикам
Постов в день
0,0
всего 21
Упоминаний
1
каналов
Охват размещения
оценка
1/24сутки в ленте
351
1/48двое суток
402
1/72трое суток
433

Оценка по просмотрам недавних постов: пост набирает почти всё за первые сутки.

Посты

  • 6 авг.396281

    Type refinements: все способы уточнить тип Type Refinement (или уточнение типа) - это процесс, при котором TypeScript сужает тип значения, переходя от более общего к более конкретному, на основе проверок, условий или контекста. Существует несколько основных способов уточнения типа. 🟣Уточнение через оператор typeof. function printValue(value: string | number) { if (typeof value === "string") { console.log(value.toUpperCase()); // string } else { console.log(value.toFixed(2)); // number } } Функция printValue принимает значение, которое может быть числом или строкой. Через проверку typeof в if блоке - мы сужаем с множества всех строк и чисел до множества строк. В ветке else, соответственно, тип автоматически станет числом. 🟣Уточнение через instanceof, когда мы работаем с классами. class User { constructor(public name: string) {} } function process(value: User | Date) { if (value instanceof User) { console.log(value.name); } else { console.log(value.toISOString()); } } Если значение является экземпляром определенного класса, TypeScript корректно сузит тип внутри этого условия и поймет, что в каждой ветке будет инстанс определенного класса. 🟣Проверка структуры объекта через оператор in. type TSuccess = { ok: true; data: string }; type TError = { ok: false; error: string }; function handle(res: TSuccess | TError) { if ("data" in res) { console.log(res.data); // TSuccess } else { console.log(res.error); // TError } } Здесь в примере у нас есть два типа, которые отличаются полями data и error. Проверив наличие поля data в объекте - тайпскрипт правильно определит с каким типом мы дальше будем работать. 🟣Использование дискриминирующих объединений. type Circle = { type: "circle"; radius: number }; type Square = { type: "square"; size: number }; type Shape = Circle | Square; function area(shape: Shape) { switch (shape.type) { case "circle": return Math.PI * shape.radius ** 2; case "square": return shape.size * shape.size; } } Это когда внутри объекта есть специальное поле, по значению которого можно однозначно определить, что это тот или иной тип. TypeScript автоматически сопоставляет значения дискриминанта и сужает тип. 🟣Также существует механизм type assertion - утверждение типа. const el = document.getElementById("div") as HTMLDivElement; Это не уточнение типа, а принудительное указание типа через оператор "as". Использовать этот механизм нужно осторожно и редко, потому что он позволяет нарушить правила типизации. При этом оператор "as" всё же проверяет пересечение типов, поэтому полностью некорректные значения передать туда не получится (скрин 1). Конечно это можно обойти тем, что сначала привести тип к unknown, а потом уже к boolean, но как минимум это заставит разработчика задуматься, не делает ли он полную глупость. ✈️ Telegram | 🎓 Менторство | 📹YouTube | 👩‍💻 Roadmap

  • 30 июн.1 2799

    без подписи

  • 30 июн.1 2502911

    WeakMap и WeakSet На защитах материала у студентов по JavaScript я регулярно вижу один и тот же пробел: когда речь заходит про встроенные структуры данных, а именно Map, Set, WeakMap и WeakSet — большинство учеников не могут полноценно объяснить, зачем нужны слабые коллекции, какие у них есть ограничения и где их можно применять. 🟣 Что это такое? WeakMap и WeakSet это специальные коллекции в JavaScript, которые позволяют хранить данные, связанные с объектами, не мешая сборщику мусора удалять их из памяти, когда они больше не используются. Их применяют, когда данные должны существовать только до тех пор, пока существует связанный с ними объект. WeakMap хранит пары «ключ - значение» и имеет методы: ➖ set — добавляет новую пару или перезаписывает значение ключа. ➖ get — возвращает значение по переданному ключу, если его нет — undefined. ➖ has — проверяет наличие ключа и возвращает true / false. ➖ delete — удаляет пару по ключу и возвращает true, если запись была удалена, иначе false. WeakSet хранит только значения и имеет методы: ➖ add — добавляет новое значение и возвращает сам WeakSet. ➖ has — проверяет наличие значения и возвращает true или false. ➖ delete — удаляет значение и возвращает true, если оно существовало, иначе false. 🟣 Что означает Weak? Обычные Map и Set хранят сильную ссылку на объект, поэтому пока объект находится внутри коллекции — сборщик мусора не сможет удалить его из памяти. А в WeakMap ссылка на ключ является «слабой». Если больше нигде на этот объект нет сильных ссылок, сборщик мусора может удалить и сам объект, и соответствующую запись в WeakMap. WeakSet работает аналогично: если объект существует только внутри WeakSet и больше нигде не используется, сборщик мусора может удалить его. При этом очистка происходит не сразу: JavaScript сам определяет момент запуска сборщика мусора, поэтому нельзя строить логику на ожидании удаления объекта. 🟣 Какие значения можно использовать? Ключами WeakMap и значениями WeakSet не могут быть примитивы, а только объекты. const users = new WeakMap(); users.set('user-1', true); // Uncaught TypeError: WeakMap key "user-1" must be an object or an unregistered symbol «Слабые» коллекции отслеживают жизненный цикл конкретного значения в памяти. У объектов есть собственные ссылки, а примитивы работают иначе. Поэтому для примитивных значений нужно использовать обычные версии. Также в актуальной спецификации есть исключение: слабые коллекции также принимают незарегистрированные Symbol'ы. Но основной сценарий их использования — работа именно с объектами. 🟣 Какие есть ограничения? У WeakMap и WeakSet нет size, keys, values, entries и forEach. Также их нельзя перебрать через for...of. Размер Weak-структур невозможно определить предсказуемо: он может измениться в любой момент после запуска сборщика мусора. Поэтому API, позволяющего узнать количество элементов или перебрать коллекцию, просто не существует. Получить данные из WeakMap или проверить наличие объекта в WeakSet можно только если у вас уже есть ссылка на этот объект. 🟣 Применение WeakMap Один из основных сценариев использования WeakMap — хранение дополнительных данных, связанных с конкретным объектом. Например, можно хранить метаданные DOM-элемента отдельно, не добавляя служебные поля прямо в него (скрин 1). После удаления DOM-элемента - запись исчезнет автоматически, без необходимости вручную очищать коллекцию. Также такой подход можно использовать для кэширования результатов, хранения приватных метаданных, состояния экземпляров классов и внутренних данных библиотек. 🟣 Применение WeakSet Допустим, мы хотим проверить объект на наличие циклических ссылок (скрин 2). Циклическая ссылка — это ситуация, когда объект прямо или косвенно ссылается сам на себя. Если при обходе мы повторно встречаем объект, который уже находится в текущем пути обхода, значит обнаружена циклическая ссылка. Такой подход может быть так же применим при валидации, сериализации, клонировании объектов и анализе сложных конфигураций. ✈️ Telegram | 🎓 Менторство | 📹YouTube | 👩‍💻 Roadmap

  • 11 июн.1 402325

    Mapped Types Готовые утилитарные типы в TypeScript основаны на мощной возможности языка создавать новые типы на основе существующих с помощью перебора ключей и трансформации значений. Этот механизм называется Mapped Types. Mapped Types решают проблему повторения структуры объектов при создании вариаций типов, например, когда нужно сделать все поля обязательными, опциональными или readonly. Мы можем создать свой Partial или Readonly. type MyPartial<T> = { [K in keyof T]?: T[K]; }; type MyReadonly<T> = { readonly [K in keyof T]: T[K]; }; type User = { name: string; age: number; }; type PartialUser = MyPartial<User>; type ReadonlyUser = MyReadonly<PartialUser>; const partialUser: PartialUser = {}; const readonlyUser: ReadonlyUser = {}; Внутри типа используется запись K in keyof T, которая означает, что мы итерируемся по ключам переданного объекта. В K попадает сам ключ, а дальше мы возвращаем его значение. Существуют следующие модификаторы: — ? для опциональности: [K in keyof T]?: T[K] — readonly, чтобы сделать значение только для чтения: readonly [K in T]: T[K] ​ С помощью знака минус можно сделать обратное действие, например, убрать readonly или сделать обязательными поля, как это реализовано, например, в типе Required. // Make all properties in T required type Required<T> = { [P in keyof T]-?: T[P]; }; ​ 🟣Можно использовать тип never для исключения значений, как это сделано в типах Exclude и Extract: // Exclude from T those types that are assignable to U type Exclude<T, U> = T extends U ? never : T; // Extract from T those types that are assignable to U type Extract<T, U> = T extends U ? T : never; 🟣В TypeScript 4.1 и выше можно менять имена свойств в mapped types с помощью конструкции as type MappedTypeWithNewProperties<Type> = { [Properties in keyof Type as NewKeyType]: Type[Properties]; }; Часть as NewKeyType говорит: «возьми старое имя свойства и преврати его в новое имя». 🟣В реальности этим не так часто приходится пользоваться в разработке. Но на собесах по TypeScript достаточно часто просят написать свою реализацию определенного утилитарного типа. ✈️ Telegram | 🎓 Менторство | 📹YouTube | 👩‍💻 Roadmap

  • 30 мая1 712396

    Стоит ли вообще входить в IT в 2026 и как это сделать? https://youtube.com/live/9YM4PeiYG4o Сегодня в 14:00 буду присутствовать на стриме с Антоном и другими менторами и обсуждать актуальные вопросы IT рынка Обсудим: • Есть ли вакансии для новичков в 2026? • AI всех заменит или это очередная страшилка? • Почему не зовут на собеседования, как увеличить конверсию откликов и подняться в выдаче HH • Как использовать AI для поиска работы и подготовки к собесам • Какие кандидаты сейчас нужны рынку? Я буду делиться несколькими советами про то как обучаться и как полезно использовать нейросети при обучении. Приходите и задавайте свои вопросы в чате!)

  • 17 мая3 2044329

    Курс по System Design В конце прошлого года поучаствовал в создании курса по System Design и вот наконец он вышел! https://youtu.be/HHQTVvMXadE https://youtu.be/HHQTVvMXadE Я отвечал за часть, связанную с фронтендом: разобрал специфику проектирования фронтенд-систем и то, как обычно проходит собеседование у фронтендеров. Таймкод моей части — 3:12:10. Но для комплексного погружения в SD - можете посмотреть весь курс, будет много полезного. Постарался сделать материал максимально прикладным, без лишней воды, чтобы получилась сконцентрированная лаконичная база. Заодно структурировал многие вещи и для себя — теперь эти материалы станут частью блока по System Design внутри сообщества Frontend Alliance. В курсе: — Какие задачи бывают на System Design — Зачем вообще проводят этот этап у фронтенд-разработчиков — Как проходит собеседование — Что такое архитектура и что относится к архитектуре фронтенда — Выбор стэка — Стратегии режимов рендера — Архитектурные подходы и методологии — BFF — UI/UX и доступность — Оптимизация производительности — Тестирование и метрики Буду рад, если посмотрите и поделитесь фидбеком. Для меня это первый опыт создания обучающих материалов и я хочу продолжать развиваться в этом ремесле. ✈️ Telegram | 🎓 Менторство | 📹 YouTube | 👩‍💻 Roadmap

  • 10 мая1 66410

    без подписи

  • 10 мая1 66310

    без подписи

  • 10 мая1 21710

    без подписи

  • 10 мая1 23110

    без подписи

  • 10 мая1 19810

    без подписи

  • 10 мая1 6603011

    Самое важное про Generics Дженерики - это производные типы, которые позволяют передавать типы в качестве аргументов, подобно тому, как функции принимают значения. Они помогают создавать переиспользуемый код для типов, избавляться от дублирования и добавлять семантическую ясность. Дженерики могут применяться к типам, интерфейсам, функциям и классам. Передаются они в угловых скобках, и их количество не ограничено. Общепринято называть первый дженерик буквой T (от слова type). Рассмотрим на примере: function merge(obj1: object, obj2: object) { return { ...obj1, ...obj2, } } const result = merge({ a: 1, b: 2 }, { a: 2, c: 3 }) console.log(result) // {a: 2, b: 2, c: 3} Допустим, мы хотим затипизировать функцию merge, которая принимает два объекта и объединяет их ключи в результирующий объект. Если указать тип параметров как object, выходной тип тоже будет object, и TypeScript не сможет подсказать, какие ключи будут доступны после объединения. Решение: использовать дженерики. Теперь мы в угловые скобки функции будем принимать два дженерика T и K, куда попадут типы объектов, которые мы передаем в функцию на 13 строке (скрин 1). Теперь TypeScript понимает, какой тип получится на выходе, и автокомплит подскажет все доступные поля. Так как дженерики могут принимать любые типы, можно случайно передать, например, число, и это будет валидно в текущем коде. А мы бы не хотели этого допустить. Чтобы ограничить возможные типы, используется ключевое слово extends. Extends накладывает ограничения на передаваемые типы и позволяет писать более безопасный код. В нашем примере мы ограничили дженерики на передачу только объектов (скрин 2). 🟣Теперь давайте взглянем на другой пример. function get(obj: object, key: string) { return obj[key] } const result = get({ name: 'Andrey', age: 27 }, 'name') console.log(result) // 'Andrey' У нас есть функция get, которая принимает объект и ключ, по которому нужно получить значение. Если типизировать её напрямую, результатом будет any. Тут нам также помогут дженерики. Тип объекта передаем дженериком T (скрин 3). Ранее я уже показывал оператор keyof, который извлекает ключи объекта, с помощью него мы как раз и получаем типы ключей переданного объекта. Но теперь мы видим, что результатом стала строка или число, хотя мы точно знаем, что если мы получаем значение по ключу name, то там должна быть строка. В данном случае keyof извлекает все возможные значения ключей. В нашем случае это может быть либо строка (Andrey), либо число (27). Чтобы уточнить тип нам опять понадобится дженерик (скрин 4). Ключ, который мы передаем вторым аргументом нужно также получать через дженерик, назовем его K. И мы обязательно должны наложить на него ограничение, что он должен быть keyof T (то есть быть одним из ключей объекта). Теперь результирующий тип выведется во время вызова функции и правильно определится. И бонусом теперь не сможем вторым аргументом в нашу функцию передать несуществующим ключ объекта - будет ошибка. 🟣Давайте рассмотрим еще один пример, который очень часто применим во фронтенд приложениях. Представим, что у нас есть несколько ручек бекенда, в которых структура ответа одинаковая для нескольких сущностей. Например, поля limit, pagination, size, next и есть поле items, которое является массивом этой сущности (скрин 5). И таких сущностей и ручек у нас в проекте много, но структура всегда одна. Это создает большую проблему дублирования кода и поддержки - ведь если изменится структура пагинации, нужно будет обновлять ее во всех интерфейсах. Написав дженерик, мы получим универсальный шаблон ответа ручек бекенда для любой сущности, нужно будет только прокинуть нужный тип (скрин 6). Теперь у нас нет дублирование кода и легко добавлять новые сущности. Если изменится контракт бекенда - правки вносятся в одном месте, что облегчает поддержку и рефакторинг. ✈️ Telegram | 🎓 Менторство | 📹 YouTube | 👩‍💻 Roadmap

  • 27 апр.1 6464

    без подписи

  • 27 апр.1 8294

    без подписи

  • 27 апр.1 5824

    без подписи

  • 27 апр.1 4384

    без подписи

  • 27 апр.1 3214

    без подписи

  • 27 апр.1 2784

    без подписи

  • 27 апр.1 640255

    Самое важное про Enum В TypeScript есть enum (сокращение от enumeration: перечисление) - это специальный тип, который позволяет создавать именованные наборы значений. Если значение не задано, элементы будут автоматически пронумерованы числами, начиная с 0. enum Status { Loading, Success, Error } let currentStatus: Status = Status.Success; console.log(currentStatus); // 1, потому что Loading = 0, Success = 1 и т.д. При этом можно задать значения явно. enum Status { Loading = 'loading', Success = 'success', Error = 'error', } let currentStatus: Status = Status.Success; console.log(currentStatus); // 'success' Enum позволяет сделать код более читаемым. Мы избегаем «магических» строк и чисел и сразу видим, какую бизнес-ценность несёт проверка. Код при этом становится самодокументируемым. 🟣Чем enum лучше обычных объектов? Проблема объектов в том, что мы не можем напрямую использовать объект как тип для типизации перечисления значений. Даже используя оператор typeof мы получим тип всего объекта, а не конкретное перечисление возможных значений (скрин 1). Enumы решает эту проблему и добавляют удобный автокомплит (скрин 2). Но важно понимать, что enumы не пропадают бесследно. Они компилируется в объект, который содержит все значения (скрин 3). Именно поэтому обычные числовые enumы имеют двустороннюю связь: по значению можно получить ключ. enum Direction { Up, // 0 } console.log(Direction[0]); // Output: "Up" 🟣С точки зрения оптимизации памяти - такой подход уступает обычным литералам. Поэтому в TypeScript существуют const enum. Вместо создания полноценного объекта при компиляции, значения подставляются напрямую как литералы, что значительно экономит память (скрин 4). 🟣Однако const enum накладывает некоторые ограничения: - Мы теперь не можем итерироваться по enumу, так как объекта физически нет (скрин 5). - Мы не можем использовать обратное отображение для числовых enumов, чтобы получить ключ по значению (скрин 6). 🟣Так же в современном TypeScript мы можем использовать объекты с as const как альтернативу enum. Эта конструкция создаёт readonly объект, где все значения используются как литералы. const Status = { Loading: 'loading', Success: 'success', Error: 'error', } as const; Вы можете спросить: как в таком случае типизировать входные данные, если обычный объект не позволял этого сделать? Благодаря константному объекту - теперь мы сможем затипизировать значения объекта с помощью двух операторов: - оператор typeof — позволяет получить тип на основе объекта. - оператор keyof — позволяет получить ключи типа. Написав соответствующую строчку, мы можем создать тип TStatus, который будет включать только конкретные значения объекта (скрин 7). ✈️ Telegram | 🎓 Менторство | 📹 YouTube | 👩‍💻 Roadmap

  • 4 апр.1 8805218

    Мок собеседование по System Design (Frontend) Недавно проверял знания Антона в проектировании архитектуры систем с упором на frontend, и в итоге мы записали полноценное мок-собеседование по System Design фронтенд части — проектировали E-commerce маркетплейс, как это делают на реальных интервью. Формат максимально сконцентрирован именно на фронтенде (так как видео по бекенду огромное количество). Прошлись по всем этапам, начиная от постановки задачи и требований до оптимизаций и метрик. Пост про выбор пагинаций из видео можно почитать здесь. В видео разобрали: — Функциональные и нефункциональные требования — Высокоуровневый дизайн — Дерево компонентов — Проектирование контрактов API — Подбор стэка и технологий — Выбор режима рендеринга — SEO — Выбор архитектуры и методологий — FSD — UI/UX и Доступность — Различные оптимизации фронтенда и системы мониторинга Посмотреть можно по ссылке: https://youtu.be/Ue6wyOFN7Zk https://youtu.be/Ue6wyOFN7Zk https://youtu.be/Ue6wyOFN7Zk ✈️ Telegram | 🎓 Менторство | 📹YouTube | 👩‍💻 Roadmap