Типизация as const
В TypeScript
Посмотрим, как это работает на практике и какие подводные камни возникают при использовании обычной типизации и
Прямое указание типа
Свойство остаётся изменяемым. Видно, что обычное указание типа не защищает от изменений.
Использование as const
В названии поля допущена ошибка (
Комбинация as const и интерфейса
Кажется логичным совместить
На практике
Readonly
Такой способ защитит от изменения свойств, а переданный тип
ReadonlyDeep
Если вам достаточно
Решение
Чтобы одновременно зафиксировать значения и проверить правильность структуры, используется оператор
При использовании конструкции
Итог
#typescript
В TypeScript
as const позволяет фиксировать значения литералов и делать их максимально конкретными: строки не расширяются до string, числа — до number, а свойства объектов и массивы становятся readonly. Это удобно, когда нужно работать с неизменяемыми объектами или использовать их как "enum-подобные" конструкции. Документация: const assertionsПосмотрим, как это работает на практике и какие подводные камни возникают при использовании обычной типизации и
as const.Прямое указание типа
type Fruit = { name: string };
const Apple: Fruit = { name: "Apple" }; // создаём объект Apple и указываем, что он имеет тип Fruit
Apple.name = "Orange"; // ⚠️ нет ошибкиСвойство остаётся изменяемым. Видно, что обычное указание типа не защищает от изменений.
Использование as const
const Apple = { nme: "Apple" } as const; // объект неизменяемый
function isFruit(payload: unknown): payload is Fruit { return payload && "name" in payload; } // простейший type-guard для наглядности
isFruit(Apple); // ⚠️ falseВ названии поля допущена ошибка (
nme вместо name), поэтому проверка не сработала. Это показывает, что as const фиксирует значения, но не гарантирует соответствие интерфейсу — легко допустить опечатку или пропустить обязательное поле.Комбинация as const и интерфейса
Кажется логичным совместить
as const с интерфейсом:const Apple: Fruit = { name: "Apple" } as const;
Apple.name = "Orange"; // ⚠️ нет ошибкиНа практике
as const "теряется": тип сужается до { name: string }, и свойство снова становится изменяемым.Readonly
const Apple: Readonly<Fruit> = { name: "Apple" };
Apple.name = "Orange"; // ✅ ошибка компиляцииТакой способ защитит от изменения свойств, а переданный тип
Fruit не даст ошибиться в названиях полей. Но есть нюанс: IDE покажет тип Apple как { name: string }, а не конкретное значение { name: "Apple" }. Будет потерян "конкретный тип", ради которого обычно и используется as const.ReadonlyDeep
Если вам достаточно
Readonly, не забывайте, что он работает только на верхнем уровне объекта: вложенные объекты и массивы останутся изменяемыми. В таких случаях стоит использовать утилиту ReadonlyDeep из type-fest. Она рекурсивно обходит все уровни и делает все свойства неизменяемыми.Решение
Чтобы одновременно зафиксировать значения и проверить правильность структуры, используется оператор
satisfies. Он проверяет, что выражение совместимо с указанным типом, при этом сохраняя исходный (более конкретный) тип для вывода. Документация: satisfies operatorconst Apple = { name: "Apple" } as const satisfies Fruit;
Apple.name = "Orange"; // ✅ ошибка компиляцииПри использовании конструкции
as const satisfies %type% TypeScript корректно проверяет правильность полей в объекте, as const сохраняет неизменность значений, а попытка присвоить новое значение свойству ловится на этапе компиляции.Итог
as const satisfies — простой способ объединить две цели: сохранить значения объекта неизменными и убедиться, что его структура соответствует интерфейсу. Особенно полезно для крупных объектов, например конфигураций, где легко допустить опечатку или ошибку в типах.#typescript
Forwarded from mefody.dev
Динамический тултип
Темани Афиф делится коротким сниппетом, который позволяет собрать тултип на чистом CSS. Тултип пытается вместиться во вьюпорт любым легальным способом. И следует за якорем.
То, для чего мы сейчас используем JS-библиотеки на 200 килобайт, можно будет заменить на пару десятков строк CSS благодаря Anchor Positioning.
(Не забывайте проверять CanIUse)
https://css-tip.com/tooltip-anchor/
Темани Афиф делится коротким сниппетом, который позволяет собрать тултип на чистом CSS. Тултип пытается вместиться во вьюпорт любым легальным способом. И следует за якорем.
То, для чего мы сейчас используем JS-библиотеки на 200 килобайт, можно будет заменить на пару десятков строк CSS благодаря Anchor Positioning.
(Не забывайте проверять CanIUse)
https://css-tip.com/tooltip-anchor/
Css-Tip
Dynamic Tooltip Position with Anchor Positioning
A tootlip that follows its anchor while adjusting the position of its tail
Сводка по переносу и обрезанию текста
Вёрстка длинных слов, URL и блоков кода часто ломает дизайн, если не использовать правильные свойства. В статье собраны ключевые приёмы:
https://js-f-k.netlify.app/articles/line-wrap
#css
Вёрстка длинных слов, URL и блоков кода часто ломает дизайн, если не использовать правильные свойства. В статье собраны ключевые приёмы:
overflow-wrap, word-break, white-space, text-overflow и text-wrap. Показано, как контролировать перенос, сохранять пробелы и добавлять многоточие, чтобы текст оставался аккуратным на любых экранах.https://js-f-k.netlify.app/articles/line-wrap
#css
Forwarded from Веб-стандарты (Vadim Makeev)
Рейтинг браузеров для PWA. Дэшборд Чарльза Уилтгена для сравнения возможностей веб-приложений в популярных мобильных браузерах (в планах и десктоп) на основе данных Can I Use и MDN: установка и манифест, уведомления, фоновые задачи, доступ к устройству, медиа и другие категории. #pwa #browsers
https://pwascore.com/
https://pwascore.com/
Forwarded from Vueist
SFC и раздутые компоненты
какое-то время в нескольких сообществах бурно обсуждаются плюсы и минусы подходы к SFC в целом. Описание всех плюсов и минусов оставлю на другой раз. Сейчас же сосредоточимся на конкретной претензии: SFC ведет к раздутым компонентам. Так ли это? А давайте разберемся с этим на примере работы в вакууме.
1. У вас есть компонент и внутри него есть template + style + script
2. В какой-то момент времени вы ловите себя на мысли "компонент стал большим, по нему неудобно навигироваться и работать с ним"
3. Вам нужно что-то предпринять
И тут у вас 2 выбора, но вначале разберем первый:
Взять компонент и посмотреть на него еще раз:
- Вынести переиспользуемую логику в композаблы
- Разбить шаблон на более базовые компоненты
- Даже банально вынести обычные утилиты из компонента
Итого получаем обратно более лаконичный компонент, он не раздут. Стало больше переиспользуемых частей. Это и есть pit of succes.
- Делать хорошо легко: маленькие компоненты легко и приятно поддерживать в SFC стиле
- Делать вербозные и раздутые компоненты неудобно, навигация усложняется и вы чувствуете как много времени уходит на что-то не то
- Есть мотивация перейти из плохого состояния в хорошее: у вас естественным образом возникает желание разбить компонент
Однако иногда система дает сбой и кому-то кажется, что решение проблемы это "а давайте разобьем компонент и вынесем из него css/html/js" не важно что. Как только вы поставили самоцелью сделать не функциональное разбиение, а типовое, то вы сразу
1) Ломаете то как работает изначальная идея: вам должно неприятно работать с раздутыми компонентами
2) Ломаете привычный флоу работы со Vue
3) Теряете плюсы которые дает SFC
И ради чего? Ради того, чтобы лечить раковую опухоль(использование практики раздутых компонентов) сбивая температуру(просто разбивая файл, а не функционал)
Надеюсь, что мораль ясна. А вам стало понятна еще одна причина, почему SFC — это хорошо
какое-то время в нескольких сообществах бурно обсуждаются плюсы и минусы подходы к SFC в целом. Описание всех плюсов и минусов оставлю на другой раз. Сейчас же сосредоточимся на конкретной претензии: SFC ведет к раздутым компонентам. Так ли это? А давайте разберемся с этим на примере работы в вакууме.
1. У вас есть компонент и внутри него есть template + style + script
2. В какой-то момент времени вы ловите себя на мысли "компонент стал большим, по нему неудобно навигироваться и работать с ним"
3. Вам нужно что-то предпринять
И тут у вас 2 выбора, но вначале разберем первый:
Взять компонент и посмотреть на него еще раз:
- Вынести переиспользуемую логику в композаблы
- Разбить шаблон на более базовые компоненты
- Даже банально вынести обычные утилиты из компонента
Итого получаем обратно более лаконичный компонент, он не раздут. Стало больше переиспользуемых частей. Это и есть pit of succes.
- Делать хорошо легко: маленькие компоненты легко и приятно поддерживать в SFC стиле
- Делать вербозные и раздутые компоненты неудобно, навигация усложняется и вы чувствуете как много времени уходит на что-то не то
- Есть мотивация перейти из плохого состояния в хорошее: у вас естественным образом возникает желание разбить компонент
Однако иногда система дает сбой и кому-то кажется, что решение проблемы это "а давайте разобьем компонент и вынесем из него css/html/js" не важно что. Как только вы поставили самоцелью сделать не функциональное разбиение, а типовое, то вы сразу
1) Ломаете то как работает изначальная идея: вам должно неприятно работать с раздутыми компонентами
2) Ломаете привычный флоу работы со Vue
3) Теряете плюсы которые дает SFC
И ради чего? Ради того, чтобы лечить раковую опухоль(использование практики раздутых компонентов) сбивая температуру(просто разбивая файл, а не функционал)
Надеюсь, что мораль ясна. А вам стало понятна еще одна причина, почему SFC — это хорошо
Почему не стоит проверять email сложными регулярными выражениями
Если у вас появилась задача "проверить полное соответствие введённого email стандарту RFC", то скорее всего вы не понимаете реальной цели формы, которую даёте на заполнение пользователю. Единственная правильная цель – убедиться, что с введённым адресом можно связаться с пользователем.
Написание сложных regex, вроде:
может быть "увлекательным" занятием, но на практике они всегда излишни.
Простая проверка
Если нужно просто убедиться, что пользователь не ошибся полем, достаточно проверить наличие символа
Если нужен более строгий подход:
- наличие хотя бы одного символа до
- наличие домена после
- наличие точки и домена верхнего уровня
Даже эта проверка чаще всего избыточна: главная задача — чтобы адрес был действующим.
Почему полноценная проверка избыточна
RFC 5322 описывает email как довольно сложную конструкцию:
- в локальной части до
- допускаются комментарии в скобках, включая вложенные
- сервер обрабатывает локальную часть по своим правилам, и нестандартные адреса могут быть валидными
Даже идеально написанный regex может отклонять рабочие адреса. Строгая проверка может оттолкнуть пользователей с нестандартными, но рабочими почтовыми серверами.
Единственный надёжный способ проверить, что email рабочий, — это отправить письмо с подтверждением. Только так вы можете убедиться, что адрес действительно существует и пользователь реально может получить на него письмо.
Базовые правила проверки
Для упрощённого взаимодействия с пользователем достаточно проверить:
- поле не пустое
- поле содержит символ
- наличие защиты от SQL-инъекций или других очевидных злоупотреблений
Итог
- Сложные regex для email почти всегда избыточны
- Базовой проверки достаточно для большинства задач
- Основной инструмент проверки — подтверждающее письмо
#html
Если у вас появилась задача "проверить полное соответствие введённого email стандарту RFC", то скорее всего вы не понимаете реальной цели формы, которую даёте на заполнение пользователю. Единственная правильная цель – убедиться, что с введённым адресом можно связаться с пользователем.
Написание сложных regex, вроде:
(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\ x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])может быть "увлекательным" занятием, но на практике они всегда излишни.
Простая проверка
Если нужно просто убедиться, что пользователь не ошибся полем, достаточно проверить наличие символа
@.Если нужен более строгий подход:
.+@.+\..+, это проверит:- наличие хотя бы одного символа до
@- наличие домена после
@- наличие точки и домена верхнего уровня
Даже эта проверка чаще всего избыточна: главная задача — чтобы адрес был действующим.
Почему полноценная проверка избыточна
RFC 5322 описывает email как довольно сложную конструкцию:
- в локальной части до
@ допустимы специальные символы- допускаются комментарии в скобках, включая вложенные
- сервер обрабатывает локальную часть по своим правилам, и нестандартные адреса могут быть валидными
Даже идеально написанный regex может отклонять рабочие адреса. Строгая проверка может оттолкнуть пользователей с нестандартными, но рабочими почтовыми серверами.
Единственный надёжный способ проверить, что email рабочий, — это отправить письмо с подтверждением. Только так вы можете убедиться, что адрес действительно существует и пользователь реально может получить на него письмо.
Базовые правила проверки
Для упрощённого взаимодействия с пользователем достаточно проверить:
- поле не пустое
- поле содержит символ
@- наличие защиты от SQL-инъекций или других очевидных злоупотреблений
Итог
- Сложные regex для email почти всегда избыточны
- Базовой проверки достаточно для большинства задач
- Основной инструмент проверки — подтверждающее письмо
#html
Forwarded from Веб-стандарты (Vadim Makeev)
Простые поля для одноразовых кодов. Тайлер Стика показывает, как создать полностью рабочее поле для одноразового пароля (OTP) с помощью одного HTML-элемента — без JavaScript, CSS-хаков и сторонних библиотек. Достаточно атрибутов
https://cloudfour.com/thinks/simple-one-time-passcode-inputs/
inputmode="numeric", autocomplete="one-time-code" и pattern="\d{6}", чтобы обеспечить автозаполнение, валидацию и доступность. Всё остальное можно добавить как прогрессивное улучшение. #html #a11yhttps://cloudfour.com/thinks/simple-one-time-passcode-inputs/
👍1
Forwarded from mefody.dev
Переезд с Chalk на нативный styleText
Есть такая утилита Chalk, которую даже если вы осознанно в проект на Node.js не подключали, есть высокая вероятность, что подключали неосознанно. У неё какое-то неприличное девятизначное число скачиваний в неделю. И нужна она, чтобы в терминале красиво выводить текст: с фоновым цветом, разноцветно, жирненько или курсивом и так далее.
В Node.js v22.13.0 стабильной стала нативная утилита
А самое приятное, что можно запустить официальный кодмод от команды Node.js, который мигрирует ваш проект сам:
https://nodejs.org/en/blog/migrations/chalk-to-styletext
Есть такая утилита Chalk, которую даже если вы осознанно в проект на Node.js не подключали, есть высокая вероятность, что подключали неосознанно. У неё какое-то неприличное девятизначное число скачиваний в неделю. И нужна она, чтобы в терминале красиво выводить текст: с фоновым цветом, разноцветно, жирненько или курсивом и так далее.
В Node.js v22.13.0 стабильной стала нативная утилита
node:util.styleText, которая может почти всё то же самое, но с некоторыми ограничениями. Для нас, разработчиков, это приятное удаление лишней зависимости и более быстрое логирование.А самое приятное, что можно запустить официальный кодмод от команды Node.js, который мигрирует ваш проект сам:
npx codemod @nodejs/chalk-to-util-styletext
https://nodejs.org/en/blog/migrations/chalk-to-styletext
nodejs.org
Node.js — Chalk to Node.js util styleText
Node.js® is a free, open-source, cross-platform JavaScript runtime environment that lets developers create servers, web apps, command line tools and scripts.
👍1
Forwarded from Веб-стандарты (Vadim Makeev)
Явное управление ресурсами в JavaScript. Мэтт Смит объясняет
https://allthingssmitty.com/2026/02/02/explicit-resource-management-in-javascript/
using и await using, а также Symbol.dispose и Symbol.asyncDispose, чтобы очистка всегда выполнялась при выходе из области видимости и в обратном порядке для нескольких ресурсов. Для большей гибкости есть DisposableStack и AsyncDisposableStack. #js #ecmasripthttps://allthingssmitty.com/2026/02/02/explicit-resource-management-in-javascript/
Автоматизация релизов на GitHub
Если вы поддерживаете несколько проектов или библиотек на GitHub и устали делать релизы вручную, шаблон Auto Release Template поможет с автоматизацией. Он генерирует changelog, создаёт коммит с новой версией, добавляет тег и публикует GitHub Release. При этом ничего не опубликуется без вашего подтверждения — всегда есть возможность проверить релиз перед публикацией. Одно из значимых отличий — в GitHub Release сразу видны все изменения, без лишней ссылки на полный changelog.
Принцип работы
1. Вносите правки и называйте коммиты по Conventional Commits.
2. Запустите
3. Вызовите
4. GitHub Action сработает на новый тег и создаст GitHub Release с автоматически сгенерированным changelog.
Настройка и кастомизация
Вы можете изменить формат коммитов, префикс тегов и определить типы коммитов, которые попадут в changelog. Дополнительно вы можете настроить:
- автопубликацию npm пакета в registry npmjs или GitHub Packages;
- использование с
- создание draft релиза;
- создание provenance statement;
- подключение хуков и добавление сгенерированных файлов в билд.
Подробные примеры для продвинутых сценариев есть в вики.
Итог
Использование Auto Release Template сокращает время на создание релизов, позволяет остановиться или откатиться на любом шаге и обеспечивает аккуратный changelog прямо в GitHub релизе. Дополнительно, с правильной настройкой GitHub Actions, это даст возможность публиковать релизы даже в приватных и командных репозиториях.
#ci #git #github #npm
Если вы поддерживаете несколько проектов или библиотек на GitHub и устали делать релизы вручную, шаблон Auto Release Template поможет с автоматизацией. Он генерирует changelog, создаёт коммит с новой версией, добавляет тег и публикует GitHub Release. При этом ничего не опубликуется без вашего подтверждения — всегда есть возможность проверить релиз перед публикацией. Одно из значимых отличий — в GitHub Release сразу видны все изменения, без лишней ссылки на полный changelog.
Принцип работы
1. Вносите правки и называйте коммиты по Conventional Commits.
2. Запустите
npm run release — обновится версия, сгенерируется CHANGELOG.md, создастся коммит и тег.3. Вызовите
git push --follow-tags.4. GitHub Action сработает на новый тег и создаст GitHub Release с автоматически сгенерированным changelog.
Настройка и кастомизация
Вы можете изменить формат коммитов, префикс тегов и определить типы коммитов, которые попадут в changelog. Дополнительно вы можете настроить:
- автопубликацию npm пакета в registry npmjs или GitHub Packages;
- использование с
pnpm;- создание draft релиза;
- создание provenance statement;
- подключение хуков и добавление сгенерированных файлов в билд.
Подробные примеры для продвинутых сценариев есть в вики.
Итог
Использование Auto Release Template сокращает время на создание релизов, позволяет остановиться или откатиться на любом шаге и обеспечивает аккуратный changelog прямо в GitHub релизе. Дополнительно, с правильной настройкой GitHub Actions, это даст возможность публиковать релизы даже в приватных и командных репозиториях.
#ci #git #github #npm
GitHub
GitHub - VChet/auto-release-template: A template for automated semantic releases using GitHub Actions
A template for automated semantic releases using GitHub Actions - VChet/auto-release-template
Forwarded from mefody.dev
Гайд по Anchor Positioning
Anchor Positioning — это декларативный способ описать визуальную привязку одного элемента к другому на странице. Тулптипы, подсказки, сноски, выносные элементы — всё это можно реализовать относительно легко при помощи Anchor Positioning API.
Рома Ахмадуллин в Доке написал подробную статью, как работать с этим однозначно полезным API. Много интерактивных демок.
https://doka.guide/css/anchor-positioning-guide/
Anchor Positioning — это декларативный способ описать визуальную привязку одного элемента к другому на странице. Тулптипы, подсказки, сноски, выносные элементы — всё это можно реализовать относительно легко при помощи Anchor Positioning API.
Рома Ахмадуллин в Доке написал подробную статью, как работать с этим однозначно полезным API. Много интерактивных демок.
https://doka.guide/css/anchor-positioning-guide/
Дока
Гайд по Anchor Positioning — CSS — Дока
Всё, что нужно знать про Anchor Positioning: основные термины, свойства и функции, полезные ссылки по теме.
👍1
Обрезание текста по центру
В статье по переносу и обрезанию текста был показан часто используемый пример с
Поскольку CSS не умеет обрезать текст в середине, строку приходится явно разбивать на две части на уровне разметки: левая может сжиматься и обрезаться, правая остаётся фиксированной и всегда отображается полностью.
Разбираем простой подход, без зависимостей и сложных вычислений ширины текста
https://js-f-k.netlify.app/articles/middle-ellipsis
#css #html
В статье по переносу и обрезанию текста был показан часто используемый пример с
text-overflow: ellipsis, где не влезающий в контейнер текст обрезается в конце. Но есть сценарии, когда требуется отобразить конец строки, а середину скрыть: UUID и хэши, email-адреса, пути к файлам, blockchain-адреса, токены и ключи.Поскольку CSS не умеет обрезать текст в середине, строку приходится явно разбивать на две части на уровне разметки: левая может сжиматься и обрезаться, правая остаётся фиксированной и всегда отображается полностью.
Разбираем простой подход, без зависимостей и сложных вычислений ширины текста
https://js-f-k.netlify.app/articles/middle-ellipsis
#css #html
Forwarded from Vueist
Мне прислали вопрос по моему докладу:
Тема на самом деле куда обширнее чем кажется на первый взгляд, Именно поэтому я добавил ее в блок "потенциальный доклад по теме", Тут будет моя адаптация ответа.
Так как композаблы сами в себе альтернатива ООП заточенная конкретно под нужды Vue. Они уже используют фичи соответствующие потребностям и отсекают вещи которые не особо нужны.
Выше уже было мое сравнение композаблов и ООП, потом в отдельных чатах эта тема прорабтывалась куда подробнее. Но тут я сосредоточусь на минусах классов как замены композаблов
1) Классы - не vue way. Ни в одном гайде не будет такого использования. Вы увеличите время онбоардинга, а разработчикам придется куда сложнее с точки зрения приспосабливаемости к проекту, Библиотеки также не адаптированы под данный подход. В одном из случаев вам придется писать огромную портянку с оберткой композаблов в классы, в другом у вас будет адская смесь из классов и композаблов. Выдерживать единый стиль в таких проектах кратно сложнее.
2) Нет четко выработанных практик о том как БЕЗОПАСНО использовать смесь Vue и классов. Высока вероятность получения хрупкого кода, потери реактивности и лапши, При этом опять же у вас не будет гайдов, как правильно это использовать в том или ином случае. Реактивность Vue не дружит полноценно с классами. Например private property несоввместимы с proxy, вам придется полагаться только на TS зоны видимости, но и с ними будут свои нюансы
3)ООП дает избыточные инструменты которые будут только мешать при использовании Vue, они хуже связываются с его жизненным циклом. Наследование, instanceof и тп просто бесполезны. А вот классическую деструктуризацию использовать сложнее
4) Вы не получите никаких бенефитов от данного подхода. Все что дает ООП и реально нужно, то возможно использовать с композаблами и так.
Так стоит ли это того? Классы часто берут по привычке, либо если почувствовали в себе труъ-инженеров (а это буквально самое страшное что может случиться с проектом, самые запущенные случаи которые видел, когда кто-то посчитал себя истинным инженером и нагородил такой лапши, что проще проект выкинуть и переписать заново, чем править его логику)
Почему же это использовали со Vue2?
- А потому что других вариантов адекватных не было. Как раз из-за отсутсвия композаблов выносить логику из компонентов для переиспользования было прям сильно сложнее, а миксины были еще хуже как решение. Вот собственно и все
Когда классы+Vue ок? Когда вы используете сторонние специализированные инструменты которые уже заточены под классовое ооп. Например, если вы подключили Mobx (хотя особого смысла я в этом тоже не вижу)
почему нежелательно использовать классы вместо компосаблов.
Тема на самом деле куда обширнее чем кажется на первый взгляд, Именно поэтому я добавил ее в блок "потенциальный доклад по теме", Тут будет моя адаптация ответа.
Так как композаблы сами в себе альтернатива ООП заточенная конкретно под нужды Vue. Они уже используют фичи соответствующие потребностям и отсекают вещи которые не особо нужны.
Выше уже было мое сравнение композаблов и ООП, потом в отдельных чатах эта тема прорабтывалась куда подробнее. Но тут я сосредоточусь на минусах классов как замены композаблов
1) Классы - не vue way. Ни в одном гайде не будет такого использования. Вы увеличите время онбоардинга, а разработчикам придется куда сложнее с точки зрения приспосабливаемости к проекту, Библиотеки также не адаптированы под данный подход. В одном из случаев вам придется писать огромную портянку с оберткой композаблов в классы, в другом у вас будет адская смесь из классов и композаблов. Выдерживать единый стиль в таких проектах кратно сложнее.
2) Нет четко выработанных практик о том как БЕЗОПАСНО использовать смесь Vue и классов. Высока вероятность получения хрупкого кода, потери реактивности и лапши, При этом опять же у вас не будет гайдов, как правильно это использовать в том или ином случае. Реактивность Vue не дружит полноценно с классами. Например private property несоввместимы с proxy, вам придется полагаться только на TS зоны видимости, но и с ними будут свои нюансы
3)ООП дает избыточные инструменты которые будут только мешать при использовании Vue, они хуже связываются с его жизненным циклом. Наследование, instanceof и тп просто бесполезны. А вот классическую деструктуризацию использовать сложнее
4) Вы не получите никаких бенефитов от данного подхода. Все что дает ООП и реально нужно, то возможно использовать с композаблами и так.
Так стоит ли это того? Классы часто берут по привычке, либо если почувствовали в себе труъ-инженеров (а это буквально самое страшное что может случиться с проектом, самые запущенные случаи которые видел, когда кто-то посчитал себя истинным инженером и нагородил такой лапши, что проще проект выкинуть и переписать заново, чем править его логику)
Почему же это использовали со Vue2?
- А потому что других вариантов адекватных не было. Как раз из-за отсутсвия композаблов выносить логику из компонентов для переиспользования было прям сильно сложнее, а миксины были еще хуже как решение. Вот собственно и все
Когда классы+Vue ок? Когда вы используете сторонние специализированные инструменты которые уже заточены под классовое ооп. Например, если вы подключили Mobx (хотя особого смысла я в этом тоже не вижу)