Галоўная / Артыкулы / Тры патэрны TypeScript, якія паспрабоўваюць паўнейшае стварэнне архітектуры дапрацоўкі React

Тры патэрны TypeScript, якія паспрабоўваюць паўнейшае стварэнне архітектуры дапрацоўкі React

Дазвольце дазнаць, як шаблоны Repository, Observer і Builder выкарыстоўваюць систему типаў TypeScript для стварэння чыстейшых і лягчэй кераваных кодавых базаў для React і Next.js.

763 слоў

Адаптаванне TypeScript не значыць яго правильна ўжыццё

Багато разработчыкаў проста дадаюць анотаціі типаў да своіх зменных і считаюць, што ўсё гатова. Але справжняя сіла TypeScript крыўціцца іншым — у структурных шаблонах, якія дапамагаюць адзначыць нестабільную базу коду ад такой, якая паступова розвиваецца.

Працаваўшы над прыкладніцамі для рэальных задач з React і Next.js, я выявіў калекцыю шаблонаў, якія справжнься змieniaюць ситуацыю. Це не абстрактныя вправы з підручнікаў — гэта рашэнняя проблем, з якімі вы фактычна станэце.

1. Шаблон репазітарыю — Аддзельнае аджыманне дадзеных

Калі вашы компоненты безпосередна вызываюць fetch(), вы ствараеце сабе прычыны для клопатных перапісваў, як толькі API змянюе свой формат.

Шаблон репазітарыю закрывае доступ да дадзеных за дапамогою чыстага інтэрфейсу:

// repositories/userRepository.ts
interface UserRepository {
  getById(id: string): Promise<User>;
  getAll(): Promise<User[]>;
}

export class ApiUserRepository implements UserRepository {
  async getById(id: string): Promise<User> {
    const res = await fetch(`/api/users/${id}`);
    return res.json();
  }

  async getAll(): Promise<User[]> {
    const res = await fetch('/api/users');
    return res.json();
  }
}

За такых умов вашы компаненты завісяць ад абстракцыі, а не ад конкрэтнай реалізацыі. Это значыць, што вы можетэ заменіць ApiUserRepository на мак-версію ў своіх тэстах, не чынячы ніякіх змян у коде UI.

2. Шаблон спостерагача — реактыўны стан без зайваго навантажэння Redux

Redux выпрацоўвае сваю задачу, але для стану, які не ўскладнены, гэта можа здавацца викорыстоўваннем велікага інструмента для маленькай задачы. Легкі, апартаваны ад класаў шаблон спостерагача, побудаваны на типаванам эмітэры з’явоў, працуе як простая альтернатыва:

// utils/eventBus.ts
type EventMap = {
  'user:loggedIn': { userId: string };
  'cart:updated': { itemCount: number };
};

class TypedEventBus {
  private listeners: Partial<{
    [K in keyof EventMap]: ((payload: EventMap[K]) => void)[]
  }> = {};

  on<K extends keyof EventMap>(event: K, cb: (payload: EventMap[K]) => void) {
    (this.listeners[event] ??= []).push(cb);
  }

  emit<K extends keyof EventMap>(event: K, payload: EventMap[K]) {
    this.listeners[event]?.forEach(cb => cb(payload));
  }
}

export const eventBus = new TypedEventBus();

Усё тут мае строгую типаванасць — няма жадных any-тыпаў, якія ховаюцца ў тэней. Это значыць, што няма жадных неяснасцей ў тым, якога формата пакет дадзеных мае чакаць адпаведны слухальнік.

3. Шаблон будоўніцы — стварэнне складных об’ектаў у павіннае рашэнне

Якщо вы колісь стикаліся з створэнням об’ектаў-фільтраў, налаштаванням запитаў API чы схем форм, наполненых вкладанымі умовамі, то шаблон Builder негайна прыносіць яснасць:

// builders/queryBuilder.ts
class QueryBuilder {
  private params: Record<string, string> = {};

  withPage(page: number) {
    this.params['page'] = String(page);
    return this;
  }

  withLimit(limit: number) {
    this.params['limit'] = String(limit);
    return this;
  }

  withSearch(term: string) {
    if (term.trim()) this.params['q'] = term;
    return this;
  }

  build(): string {
    return new URLSearchParams(this.params).toString();
  }
}

// Usage
const query = new QueryBuilder()
  .withPage(1)
  .withLimit(20)
  .withSearch('typescript')
  .build();
// → "page=1&limit=20&q=typescript"

Рэзультуючы код чытаецца легка, елементы ў яму з’ѐднуюцца апрано, і структурна немагчыма вызваць крокі в неправильной последовасці.

Ключавыя моманты

  • Шаблон Repository: аддзеляе шар доступу да дадзэнняў ад логіки UI, следуючы прынцыпу інверсіі залежнасцяў
  • Шаблон Observer: дазволяе лёгкую, рэакtyўную комунікацыю межа часткамі вашага прыладу без зайваго коду
  • Шаблон Builder: робіць стварэнне складных об’ектаў чытабельным і безпечным
  • Усе тры шаблоны значна выгадваюць ад інтэрфейсаў і генерыкаў у TypeScript, чым стаюць значна чыстэйшыя за сваі аналогі ў звычным JavaScript

«TypeScript — гэта не проста можлівасць дадзець типы; гэта средства для ствароўкі адносаў межы кожным слайам вашага прыемніка.» — Дэн Вандеркам, аўтар кнігі Effective TypeScript

Што працаваць далей

Выберыце адну з патэранаў, описаных у гэтым артыкуле, і застосавыце яе да рэальнага модуля у вашай базе коду ў гэты тыдзень. Працаваць трэба пашагоўна, памятаючы, што гэтыя патэраны — це інструменты, а не правілы.

Наймоцнейшыя базы коду визначаюцца не колькістю типоў, якія ў іх є, нават у проектах на TypeScript. Їх визначае цэлеспрямованасць — кожны патэран тамтэў, таму што ён заслужыў свае месца.

Спаднія матэрыялы

  • Калі AI пішчытае ваш React-проект, але ігнаруе прынцыпы чыстага коду — Дазвольце вы мяркаваць сэвёсныя прынцыпы чыстага коду — DRY, адна адпаведальнасць, клазусы захавання і іншыя — якія часта нарабляецца код у React, створаны AI, не дазволяе сабліжваць, і як іх паспраўляць.
  • Розумеўце React Lanes: як бітмаскі кодуюць прыоритэт апдэйтаў — Дазвольце вы дазнацца, як React используе бітмаскі, каб закодаваць калькольныя прыоритэты апдэйтаў у адзін цэлычны числовы значэнне, і чаму для планавання заместа простых булевых флагоў выкарыстоўваюцца бітовыя аперацыі.