10 промтов для генерации JavaScript и TypeScript кода: React, Node.js, утилиты

10 промтов для генерации JavaScript и TypeScript кода: React, Node.js, утилиты

Генерация кода с помощью ИИ — не футуризм, а повседневная реальность для разработчиков. Согласно опросу Stack Overflow 2025 года, более 60% респондентов используют AI-инструменты для написания кода, особенно для JavaScript и TypeScript. Эти языки — основа современного веба, от React-приложений до Node.js-серверов. Но чтобы ИИ выдавал качественный код, нужно правильно формулировать промты. В этой подборке — 10 проверенных шаблонов, которые я использую в работе. Каждый промт включает проблему, решение и пример кода.

1. Генерация React-компонента с TypeScript

Проблема: Нужно быстро создать типизированный компонент с обработчиками событий и пропсами. Решение: Промт для генерации компонента с явными типами. Результат: Экономия времени на шаблонном коде.
Промт: «Создай React-компонент на TypeScript для отображения списка задач (TodoList). Компонент принимает массив объектов { id: number, title: string, completed: boolean } и функцию onToggle для изменения статуса. Используй useState для локального состояния, если нужно. Добавь стили через CSS-in-JS (styled-components).»
Код:

import React, { useState } from 'react';
import styled from 'styled-components';

interface Todo {
  id: number;
  title: string;
  completed: boolean;
}

interface TodoListProps {
  todos: Todo[];
  onToggle: (id: number) => void;
}

const List = styled.ul`
  list-style: none;
  padding: 0;
`;

const Item = styled.li<{ completed: boolean }>`
  text-decoration: ${props => props.completed ? 'line-through' : 'none'};
  cursor: pointer;
`;

const TodoList: React.FC<TodoListProps> = ({ todos, onToggle }) => {
  return (
    <List>
      {todos.map(todo => (
        <Item key={todo.id} completed={todo.completed} onClick={() => onToggle(todo.id)}>
          {todo.title}
        </Item>
      ))}
    </List>
  );
};

export default TodoList;

2. Создание Express-маршрута с валидацией

Проблем: Нужен REST API эндпоинт с проверкой входных данных. Решение: Промт для генерации маршрута с Joi-валидацией. Результат: Безопасный код без ручного написания проверок.
Промт: «Напиши Express.js роутер на TypeScript для POST /api/users. В теле запроса: name (строка, обязательное), email (строка, валидный email). Используй библиотеку Joi для валидации. При ошибке верни статус 400 и сообщение. Добавь async/await и обработку ошибок через try/catch.»
Код:

import { Router, Request, Response } from 'express';
import Joi from 'joi';

const router = Router();

const schema = Joi.object({
  name: Joi.string().required(),
  email: Joi.string().email().required(),
});

router.post('/users', async (req: Request, res: Response) => {
  try {
    const { error, value } = schema.validate(req.body);
    if (error) {
      return res.status(400).json({ message: error.details[0].message });
    }
    // Здесь логика создания пользователя
    res.status(201).json({ id: Date.now(), ...value });
  } catch (err) {
    res.status(500).json({ message: 'Internal server error' });
  }
});

export default router;

3. Утилита для глубокого клонирования объекта

Проблем: Нужна надёжная функция без внешних зависимостей. Решение: Промт для реализации с учётом краевых случаев. Результат: Готовая утилита для продакшена.
Промт: «Напиши функцию на TypeScript для глубокого клонирования объекта. Обработай: вложенные объекты, массивы, null, Date, RegExp, Map, Set. Не используй JSON.parse/JSON.stringify. Используй рекурсию. Типизируй возвращаемое значение.»
Код:

function deepClone<T>(obj: T, hash = new WeakMap()): T {
  if (obj === null || typeof obj !== 'object') return obj;
  if (hash.has(obj)) return hash.get(obj);
  if (obj instanceof Date) return new Date(obj) as any;
  if (obj instanceof RegExp) return new RegExp(obj) as any;
  if (obj instanceof Map) {
    const clone = new Map();
    obj.forEach((val, key) => clone.set(key, deepClone(val, hash)));
    hash.set(obj, clone);
    return clone as any;
  }
  if (obj instanceof Set) {
    const clone = new Set();
    obj.forEach(val => clone.add(deepClone(val, hash)));
    hash.set(obj, clone);
    return clone as any;
  }
  const cloneObj = Array.isArray(obj) ? [] : {};
  hash.set(obj, cloneObj);
  for (const key in obj) {
    if (obj.hasOwnProperty(key)) {
      (cloneObj as any)[key] = deepClone((obj as any)[key], hash);
    }
  }
  return cloneObj as T;
}

4. Хук для работы с localStorage в React

Проблем: Синхронизация состояния с localStorage при изменениях. Решение: Кастомный хук с подпиской на storage event. Результат: Удобный инструмент для кэширования на клиенте.
Промт: «Создай кастомный React хук useLocalStorage на TypeScript. Принимает ключ и начальное значение. Возвращает [value, setValue]. При изменении значения обновляй localStorage и синхронизируй между вкладками через window.addEventListener('storage'). Типизируй с дженериками.»
Код:

import { useState, useEffect, useCallback } from 'react';

function useLocalStorage<T>(key: string, initialValue: T): [T, (value: T | ((prev: T) => T)) => void] {
  const [storedValue, setStoredValue] = useState<T>(() => {
    try {
      const item = window.localStorage.getItem(key);
      return item ? JSON.parse(item) : initialValue;
    } catch {
      return initialValue;
    }
  });

  const setValue = useCallback((value: T | ((prev: T) => T)) => {
    setStoredValue(prev => {
      const newValue = value instanceof Function ? value(prev) : value;
      window.localStorage.setItem(key, JSON.stringify(newValue));
      return newValue;
    });
  }, [key]);

  useEffect(() => {
    const handleStorageChange = (e: StorageEvent) => {
      if (e.key === key && e.newValue) {
        setStoredValue(JSON.parse(e.newValue));
      }
    };
    window.addEventListener('storage', handleStorageChange);
    return () => window.removeEventListener('storage', handleStorageChange);
  }, [key]);

  return [storedValue, setValue];
}

export default useLocalStorage;

5. Генерация тестов для функции

Проблем: Нужно быстро покрыть код unit-тестами. Решение: Промт для Jest с иcпользованием describe/it. Результат: Набор тестов, проверяющих граничные случаи.
Промт: «Напиши тесты на Jest для функции deepClone из предыдущего примера. Проверь: клонирование примитивов, вложенных объектов, массивов, Date, Map, Set. Убедись, что изменения в клоне не влияют на оригинал. Используй describe и it.»
Код:

describe('deepClone', () => {
  it('should clone primitive values', () => {
    expect(deepClone(42)).toBe(42);
    expect(deepClone('hello')).toBe('hello');
  });

  it('should clone nested objects', () => {
    const obj = { a: { b: 1 } };
    const clone = deepClone(obj);
    clone.a.b = 2;
    expect(obj.a.b).toBe(1);
  });

  it('should clone Date', () => {
    const date = new Date();
    const clone = deepClone(date);
    expect(clone).toEqual(date);
    expect(clone).not.toBe(date);
  });

  it('should clone Map', () => {
    const map = new Map([[1, 'a']]);
    const clone = deepClone(map);
    clone.set(2, 'b');
    expect(map.size).toBe(1);
  });
});

6. Асинхронный обработчик ошибок для Express

Проблем: Повторяющийся код try/catch в каждом маршруте. Решение: Функция-обёртка. Результат: Чистый код без дублирования.
Промт: «Напиши утилиту на TypeScript для оборачивания асинхронных Express-обработчиков, чтобы автоматически передавать ошибки в next(). Используй дженерики для типов req/res/next.»
Код:

import { Request, Response, NextFunction, RequestHandler } from 'express';

type AsyncHandler = (req: Request, res: Response, next: NextFunction) => Promise<any>;

const asyncHandler = (fn: AsyncHandler): RequestHandler => {
  return (req, res, next) => {
    Promise.resolve(fn(req, res, next)).catch(next);
  };
};

export default asyncHandler;

7. Генерация Zod-схемы для валидации форм

Проблем: Нужна типобезопасная валидация без Joi. Решение: Промт для Zod с интеграцией с TypeScript. Результат: Схема, генерирующая типы автоматически.
Промт: «Создай Zod-схему для формы регистрации: username (от 3 до 20 символов), email (валидный email), password (минимум 8 символов, одна заглавная буква и цифра). Выведи инференс типа через z.infer. Добавь кастомное сообщение об ошибке для поля password.»
Код:

import { z } from 'zod';

export const registrationSchema = z.object({
  username: z.string().min(3, 'Минимум 3 символа').max(20, 'Максимум 20 символов'),
  email: z.string().email('Неверный формат email'),
  password: z.string()
    .min(8, 'Минимум 8 символов')
    .regex(/[A-Z]/, 'Должна быть заглавная буква')
    .regex(/\d/, 'Должна быть цифра'),
});

export type RegistrationForm = z.infer<typeof registrationSchema>;

8. Утилита для Debounce с TypeScript

Проблем: Нужен debounce для поискового инпута без внешних библиотек. Решение: Функция с правильной типизацией. Результат: Эффективная обработка ввода.
Промт: «Напиши функцию debounce на TypeScript. Принимает функцию и задержку. Возвращает новую функцию с тем же типом, но отложенным вызовом. Добавь отмену через .cancel(). Учти контекст this.»
Код:

function debounce<T extends (...args: any[]) => any>(
  fn: T,
  delay: number
): ((...args: Parameters<T>) => void) & { cancel: () => void } {
  let timer: ReturnType<typeof setTimeout> | null = null;

  const debounced = (...args: Parameters<T>) => {
    if (timer) clearTimeout(timer);
    timer = setTimeout(() => {
      fn(...args);
      timer = null;
    }, delay);
  };

  debounced.cancel = () => {
    if (timer) {
      clearTimeout(timer);
      timer = null;
    }
  };

  return debounced;
}

export default debounce;

9. Генерация enum для статусов заказа

Проблем: Нужен строгий тип для статусов в E-commerce. Решение: Промт для создания enum с описанием. Результат: Читаемый код без магических строк.
Промт: «Создай TypeScript enum для статусов заказа: PENDING, PROCESSING, SHIPPED, DELIVERED, CANCELLED. Добавь функцию getStatusLabel, возвращающую русскоязычное описание. Используй const enum для оптимизации.»
Код:

const enum OrderStatus {
  PENDING = 'PENDING',
  PROCESSING = 'PROCESSING',
  SHIPPED = 'SHIPPED',
  DELIVERED = 'DELIVERED',
  CANCELLED = 'CANCELLED',
}

const statusLabels: Record<OrderStatus, string> = {
  [OrderStatus.PENDING]: 'Ожидает обработки',
  [OrderStatus.PROCESSING]: 'В обработке',
  [OrderStatus.SHIPPED]: 'Отправлен',
  [OrderStatus.DELIVERED]: 'Доставлен',
  [OrderStatus.CANCELLED]: 'Отменён',
};

function getStatusLabel(status: OrderStatus): string {
  return statusLabels[status];
}

export { OrderStatus, getStatusLabel };

10. Функция для пагинации массива

Проблем: Нужна утилита для разбивки данных на страницы. Решение: Промт с учётом типов. Результат: Универсальный helper для списков.
Промт: «Напиши функцию paginate на TypeScript, которая принимает массив любого типа, номер страницы (page) и размер страницы (pageSize). Возвращает объект { data, total, page, pageSize, totalPages }. Обработай краевые случаи: page < 1, pageSize <= 0.»
Код:

interface PaginatedResult<T> {
  data: T[];
  total: number;
  page: number;
  pageSize: number;
  totalPages: number;
}

function paginate<T>(items: T[], page: number = 1, pageSize: number = 10): PaginatedResult<T> {
  const safePage = Math.max(1, page);
  const safeSize = Math.max(1, pageSize);
  const total = items.length;
  const totalPages = Math.ceil(total / safeSize);
  const start = (safePage - 1) * safeSize;
  const data = items.slice(start, start + safeSize);

  return { data, total, page: safePage, pageSize: safeSize, totalPages };
}

export default paginate;

Заключение

Эти 10 промтов покрывают большинство повседневных задач: от создания компонентов до утилит и тестов. Главное — всегда указывать типы, краевые случаи и желаемый результат. С практикой вы научитесь формулировать запросы так, чтобы код с первого раза был готов к продакшену. Попробуйте применить эти промты в своём проекте — и вы увидите, как ускорится разработка. А если хотите глубже изучить генерацию кода, загляните в наш блог — там ещё больше примеров и шаблонов.

← Все статьи

Комментарии

Читайте также

Что общего у дзета-функции Римана и распределения простых чисел?

20 июля 2026

Курс «Маркетинг и SMM»: как AI-обучение помогает освоить воронку продаж и аналитику соцсетей в 2026 году

20 июля 2026

Claude опроверг знаменитую гипотезу якобиана: 87 лет математической загадки и одна минута проверки

20 июля 2026

Как создать дашборд продаж в Power BI: пошаговый гайд и обзор курса BI-аналитика и дашборды на Asibiont

20 июля 2026

10 промтов для IoT и Embedded: сенсоры, ESP32, MQTT и автоматизация

20 июля 2026

Google добавил AI-отчёты в Search Console: что они показывают на самом деле

20 июля 2026

От усталости от оповещений до MTTR за 5 минут: Как Datadog + AI-агент ASI Biont преобразуют реагирование на инциденты

20 июля 2026

Курс «Кибербезопасность» на Asibiont: как AI-обучение помогает освоить этичный хакинг с нуля

20 июля 2026

Интеграция Linode с AI-агентом ASI Biont: автоматизация управления облаком с помощью естественного языка в 2026 году

20 июля 2026