PassFront
  1. PassFront
  2. База знаний
  3. SOLID во фронтенде

Как принцип разделения интерфейсов помогает проектировать пропсы и типы в TypeScript?

SOLID во фронтенде

ISP в TypeScript: компонент или функция объявляет в типе только то, что реально читает, — не весь `User` из API, а `Pick<User, 'name' | 'avatarUrl'>`.

Проблема толстых пропсов

  • Avatar принимает user: User с 30 полями, а использует два. В Storybook и тестах нужен полный мок, а изменение схемы API ломает компиляцию там, где поле даже не читается.
  • Компонент не переиспользовать для Author или Employee, хотя у них те же name и avatarUrl.

Приёмы

  • Узкие типы: Pick, Omit, собственные интерфейсы-роли.
  • Структурная типизация: подходит любой объект нужной формы, implements не нужен.
  • Роли в сервисах: Readable<T> и Writable<T> вместо Repository<T> на 12 методов.
  • Из стора — селектор с нужным срезом, а не весь стейт: заодно меньше лишних ререндеров.
  • Обёртка над нативной кнопкой: расширить ComponentPropsWithoutRef<'button'>, остальное передать через ...rest.
interface User { id: string; name: string; avatarUrl: string; roles: string[] }
type AvatarProps = Pick<User, 'name' | 'avatarUrl'>;

function Avatar({ name, avatarUrl }: AvatarProps) {
  return <img src={avatarUrl} alt={name} />;
}

const author = { name: 'Ann', avatarUrl: '/ann.png', bio: 'Editor' };
const el = <Avatar {...author} />; // не User, но подходит по форме

Перегиб

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

Коротко для собеседования

Тип пропсов описывает только поля, которые компонент читает, — через Pick или узкий тип-роль. Благодаря структурной типизации такой компонент принимает любой объект подходящей формы, моки в тестах маленькие, а смена схемы API не ломает лишнего.

Другие вопросы раздела