30 Prompts for Generating JavaScript and TypeScript Code: From React Components to Node.js Utilities

Introduction

In 2026, generating JavaScript and TypeScript code with AI has become an integral part of the developer workflow. According to a 2025 Stack Overflow survey, over 70% of developers use AI coding assistants at least weekly, with JavaScript and TypeScript being the most common languages for prompt-based generation. This article provides a structured collection of 30 prompts organized by skill level—basic, advanced, and expert—to help you generate production-ready code for React, Node.js, and common utilities.

Whether you are a junior developer looking to scaffold components quickly or a senior engineer optimizing complex algorithms, these prompts are designed to be directly copy-pasted into tools like ChatGPT, Claude, or GitHub Copilot. Each prompt includes a clear task, the prompt itself, and an example result with code snippets.

Basic Prompts

These prompts are ideal for beginners or for generating simple, well-documented code snippets. They focus on common patterns and straightforward implementations.

1. Generate a React Functional Component

Task: Create a functional React component with props and TypeScript interfaces.

Prompt:

Generate a React functional component in TypeScript that displays a user card.
Include props for name, email, and avatar URL. Use Tailwind CSS for styling.
Add default props and a loading state.

Example Result:

interface UserCardProps {
  name: string;
  email: string;
  avatarUrl?: string;
}

const UserCard: React.FC<UserCardProps> = ({ name, email, avatarUrl }) => {
  return (
    <div className="flex items-center p-4 border rounded-lg shadow-sm">
      <img
        src={avatarUrl || '/default-avatar.png'}
        alt={name}
        className="w-12 h-12 rounded-full"
      />
      <div className="ml-4">
        <h2 className="text-lg font-semibold">{name}</h2>
        <p className="text-gray-500">{email}</p>
      </div>
    </div>
  );
};

export default UserCard;

2. Generate a Simple Node.js Express API Endpoint

Task: Create a REST API endpoint with error handling.

Prompt:

Generate an Express.js route in TypeScript for fetching a user by ID from a PostgreSQL database.
Use parameterized queries to prevent SQL injection, and include proper HTTP status codes.

Example Result:

import { Request, Response } from 'express';
import { Pool } from 'pg';

const pool = new Pool();

export const getUser = async (req: Request, res: Response) => {
  try {
    const { id } = req.params;
    const result = await pool.query('SELECT * FROM users WHERE id = $1', [id]);
    if (result.rows.length === 0) {
      return res.status(404).json({ error: 'User not found' });
    }
    res.json(result.rows[0]);
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: 'Internal server error' });
  }
};

3. Generate a Utility Function for Debouncing

Task: Write a generic debounce utility in TypeScript.

Prompt:

Write a TypeScript utility function that debounces any async function.
The function should return a debounced version with a configurable delay.
Include proper types.

Example Result:

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

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

4. Generate a Custom React Hook for Form Handling

Task: Create a custom hook for managing form state with validation.

Prompt:

Create a custom React hook called useForm that manages form state, handles input changes,
and validates required fields. Use TypeScript generics for the form values type.

Example Result:

import { useState, ChangeEvent } from 'react';

type ValidationErrors<T> = Partial<Record<keyof T, string>>;

export function useForm<T extends Record<string, any>>(initialValues: T) {
  const [values, setValues] = useState<T>(initialValues);
  const [errors, setErrors] = useState<ValidationErrors<T>>({});

  const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
    const { name, value } = e.target;
    setValues(prev => ({ ...prev, [name]: value }));
    setErrors(prev => ({ ...prev, [name]: undefined }));
  };

  const validate = (requiredFields: (keyof T)[]): boolean => {
    const newErrors: ValidationErrors<T> = {};
    requiredFields.forEach(field => {
      if (!values[field]) {
        newErrors[field] = `${String(field)} is required`;
      }
    });
    setErrors(newErrors);
    return Object.keys(newErrors).length === 0;
  };

  return { values, errors, handleChange, validate };
}

5. Generate a TypeScript Enum and Its Usage

Task: Define an enum for HTTP status codes and a function to get the message.

Prompt:

Generate a TypeScript enum for common HTTP status codes (200, 201, 400, 401, 404, 500).
Then write a function that takes a status code and returns the corresponding message.

Example Result:

enum HttpStatus {
  OK = 200,
  Created = 201,
  BadRequest = 400,
  Unauthorized = 401,
  NotFound = 404,
  InternalServerError = 500,
}

function getStatusMessage(status: HttpStatus): string {
  const messages: Record<HttpStatus, string> = {
    [HttpStatus.OK]: 'Success',
    [HttpStatus.Created]: 'Resource created',
    [HttpStatus.BadRequest]: 'Bad request',
    [HttpStatus.Unauthorized]: 'Unauthorized',
    [HttpStatus.NotFound]: 'Not found',
    [HttpStatus.InternalServerError]: 'Internal server error',
  };
  return messages[status] || 'Unknown status';
}

Advanced Prompts

These prompts are suitable for intermediate developers and cover real-world patterns like state management, authentication, and database operations.

6. Generate a Redux Toolkit Slice

Task: Create a Redux slice for managing a list of tasks with async thunks.

Prompt:

Generate a Redux Toolkit slice in TypeScript for a todo list.
Include actions for adding, toggling, and deleting tasks, plus an async thunk to fetch tasks from an API.
Use createAsyncThunk and handle pending, fulfilled, and rejected states.

Example Result:

import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit';

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

interface TodoState {
  items: Todo[];
  loading: boolean;
  error: string | null;
}

const initialState: TodoState = {
  items: [],
  loading: false,
  error: null,
};

export const fetchTodos = createAsyncThunk('todos/fetchTodos', async () => {
  const response = await fetch('/api/todos');
  return (await response.json()) as Todo[];
});

const todoSlice = createSlice({
  name: 'todos',
  initialState,
  reducers: {
    addTodo: (state, action: PayloadAction<Todo>) => {
      state.items.push(action.payload);
    },
    toggleTodo: (state, action: PayloadAction<number>) => {
      const todo = state.items.find(t => t.id === action.payload);
      if (todo) todo.completed = !todo.completed;
    },
    deleteTodo: (state, action: PayloadAction<number>) => {
      state.items = state.items.filter(t => t.id !== action.payload);
    },
  },
  extraReducers: (builder) => {
    builder
      .addCase(fetchTodos.pending, (state) => { state.loading = true; })
      .addCase(fetchTodos.fulfilled, (state, action) => {
        state.loading = false;
        state.items = action.payload;
      })
      .addCase(fetchTodos.rejected, (state, action) => {
        state.loading = false;
        state.error = action.error.message || 'Failed to fetch';
      });
  },
});

export const { addTodo, toggleTodo, deleteTodo } = todoSlice.actions;
export default todoSlice.reducer;

7. Generate a JWT Authentication Middleware for Express

Task: Create middleware to verify JWT tokens and attach user info to the request.

Prompt:

Write an Express middleware in TypeScript that verifies a JWT token from the Authorization header.
If valid, attach the decoded user to req.user. If invalid, return 401. Use jsonwebtoken library.

Example Result:

import { Request, Response, NextFunction } from 'express';
import jwt from 'jsonwebtoken';

interface AuthRequest extends Request {
  user?: { id: number; email: string };
}

export const authenticate = (req: AuthRequest, res: Response, next: NextFunction) => {
  const authHeader = req.headers.authorization;
  if (!authHeader || !authHeader.startsWith('Bearer ')) {
    return res.status(401).json({ error: 'No token provided' });
  }

  const token = authHeader.split(' ')[1];
  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET!) as { id: number; email: string };
    req.user = decoded;
    next();
  } catch (error) {
    return res.status(401).json({ error: 'Invalid token' });
  }
};

8. Generate a Custom React Hook for Local Storage with TypeScript

Task: Create a hook that syncs state with localStorage.

Prompt:

Write a custom React hook useLocalStorage that stores and retrieves a value from localStorage.
Use TypeScript generics for type safety. Include error handling for JSON parsing.

Example Result:

import { useState, useEffect } from 'react';

export function useLocalStorage<T>(key: string, initialValue: T): [T, (value: T) => void] {
  const [storedValue, setStoredValue] = useState<T>(() => {
    try {
      const item = window.localStorage.getItem(key);
      return item ? (JSON.parse(item) as T) : initialValue;
    } catch (error) {
      console.error(`Error reading localStorage key "${key}":`, error);
      return initialValue;
    }
  });

  const setValue = (value: T) => {
    try {
      setStoredValue(value);
      window.localStorage.setItem(key, JSON.stringify(value));
    } catch (error) {
      console.error(`Error setting localStorage key "${key}":`, error);
    }
  };

  return [storedValue, setValue];
}

9. Generate a TypeScript Class for a Data Model with Validation

Task: Define a User model class with validation methods.

Prompt:

Create a TypeScript class User with properties id, name, email, and age.
Include a validate method that returns an array of validation errors.
Email must be valid format, name non-empty, age between 18 and 120.

Example Result:

class User {
  constructor(
    public id: number,
    public name: string,
    public email: string,
    public age: number
  ) {}

  validate(): string[] {
    const errors: string[] = [];
    if (!this.name || this.name.trim().length === 0) {
      errors.push('Name is required');
    }
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    if (!emailRegex.test(this.email)) {
      errors.push('Invalid email format');
    }
    if (this.age < 18 || this.age > 120) {
      errors.push('Age must be between 18 and 120');
    }
    return errors;
  }
}

10. Generate an Axios Interceptor for API Calls

Task: Create an Axios interceptor to add auth tokens and handle errors globally.

Prompt:

Write an Axios instance in TypeScript with a request interceptor that adds an Authorization header
from localStorage, and a response interceptor that logs errors and redirects on 401.

Example Result:

import axios, { AxiosError } from 'axios';

const apiClient = axios.create({
  baseURL: process.env.REACT_APP_API_URL,
});

apiClient.interceptors.request.use((config) => {
  const token = localStorage.getItem('token');
  if (token) {
    config.headers.Authorization = `Bearer ${token}`;
  }
  return config;
});

apiClient.interceptors.response.use(
  (response) => response,
  (error: AxiosError) => {
    if (error.response?.status === 401) {
      localStorage.removeItem('token');
      window.location.href = '/login';
    }
    return Promise.reject(error);
  }
);

export default apiClient;

Expert Prompts

These prompts target senior developers and cover complex scenarios like microservices, stream processing, and advanced TypeScript patterns.

11. Generate a Microservice with Express and TypeScript

Task: Create a full microservice for user management with database, logging, and health checks.

Prompt:

Generate a complete Express microservice in TypeScript for user CRUD operations.
Include: database connection (MongoDB with Mongoose), structured logging with winston,
a health check endpoint, and environment configuration. Use dependency injection pattern.

Example Result (abbreviated):

// src/app.ts
import express from 'express';
import mongoose from 'mongoose';
import winston from 'winston';
import { userRouter } from './routes/userRoutes';

const app = express();

// Logger setup
const logger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  transports: [new winston.transports.Console()],
});

// Database connection
mongoose.connect(process.env.MONGO_URI!)
  .then(() => logger.info('Connected to MongoDB'))
  .catch((err) => logger.error('MongoDB connection error:', err));

// Middleware
app.use(express.json());
app.use('/api/users', userRouter);

// Health check
app.get('/health', (req, res) => res.json({ status: 'ok' }));

export { app, logger };

12. Generate a WebSocket Server with Authentication

Task: Create a WebSocket server that authenticates users and broadcasts messages.

Prompt:

Write a WebSocket server using the ws library in Node.js with TypeScript.
Authenticate users via a token sent in the connection query string.
Support join room, leave room, and send message commands.

Example Result:

import { WebSocketServer, WebSocket } from 'ws';
import jwt from 'jsonwebtoken';

interface AuthenticatedSocket extends WebSocket {
  userId?: number;
  room?: string;
}

const wss = new WebSocketServer({ port: 8080 });

wss.on('connection', (ws: AuthenticatedSocket, req) => {
  const url = new URL(req.url!, 'http://localhost');
  const token = url.searchParams.get('token');
  try {
    const decoded = jwt.verify(token!, process.env.JWT_SECRET!) as { id: number };
    ws.userId = decoded.id;
  } catch {
    ws.close(4001, 'Authentication failed');
    return;
  }

  ws.on('message', (data) => {
    const message = JSON.parse(data.toString());
    if (message.type === 'join') {
      ws.room = message.room;
    }
    // Broadcast to room
    wss.clients.forEach((client) => {
      if ((client as AuthenticatedSocket).room === ws.room && client !== ws) {
        client.send(JSON.stringify({ from: ws.userId, text: message.text }));
      }
    });
  });
});

13. Generate a Complex TypeScript Type System with Conditional Types

Task: Create a type-safe API response wrapper with conditional types.

Prompt:

Define TypeScript types for an API response wrapper that can be either success or error.
Use conditional types to infer the data type based on the status field.
Include a helper function to parse the response.

Example Result:

type ApiResponse<T> =
  | { status: 'success'; data: T }
  | { status: 'error'; error: string };

type ExtractData<T> = T extends { status: 'success'; data: infer U } ? U : never;

function parseResponse<T>(response: ApiResponse<T>): ExtractData<ApiResponse<T>> | null {
  if (response.status === 'success') {
    return response.data as ExtractData<ApiResponse<T>>;
  }
  console.error(response.error);
  return null;
}

14. Generate a Rate Limiter Middleware for Express

Task: Implement a sliding window rate limiter using Redis.

Prompt:

Create a rate limiter middleware in TypeScript using ioredis.
Use a sliding window algorithm: allow N requests per minute per IP.
Return 429 with Retry-After header when limit exceeded.

Example Result:

import { Request, Response, NextFunction } from 'express';
import Redis from 'ioredis';

const redis = new Redis();
const WINDOW_SIZE = 60; // seconds
const MAX_REQUESTS = 100;

export const rateLimiter = async (req: Request, res: Response, next: NextFunction) => {
  const ip = req.ip;
  const key = `rate_limit:${ip}`;
  const now = Math.floor(Date.now() / 1000);
  const windowStart = now - WINDOW_SIZE;

  // Remove old entries
  await redis.zremrangebyscore(key, 0, windowStart);
  // Count current entries
  const count = await redis.zcard(key);

  if (count >= MAX_REQUESTS) {
    const oldest = await redis.zrange(key, 0, 0, 'WITHSCORES');
    const retryAfter = WINDOW_SIZE - (now - parseInt(oldest[1]));
    res.set('Retry-After', String(Math.ceil(retryAfter)));
    return res.status(429).json({ error: 'Too many requests' });
  }

  await redis.zadd(key, now, `${now}-${Math.random()}`);
  await redis.expire(key, WINDOW_SIZE);
  next();
};

15. Generate a Stream Processing Pipeline for Large JSON Files

Task: Write a Node.js script to process a large JSON file line by line using streams.

Prompt:

Write a TypeScript script that reads a large JSON array file (like an array of objects)
using a streaming approach with JSONStream or similar. Filter objects by a condition
and write results to a new file. Handle backpressure properly.

Example Result:

import fs from 'fs';
import JSONStream from 'JSONStream';
import { Transform } from 'stream';

const inputStream = fs.createReadStream('input.json');
const outputStream = fs.createWriteStream('output.json');

const filterTransform = new Transform({
  objectMode: true,
  transform(chunk: any, encoding, callback) {
    if (chunk.active === true) {
      this.push(chunk);
    }
    callback();
  },
});

inputStream
  .pipe(JSONStream.parse('*'))
  .pipe(filterTransform)
  .pipe(JSONStream.stringify(false))
  .pipe(outputStream);

outputStream.on('finish', () => console.log('Done'));

Conclusion

Generating JavaScript and TypeScript code with prompts is a powerful way to accelerate development, but the quality of the output depends heavily on the specificity of the input. The 15 prompts provided here cover a wide range of scenarios—from simple React components and utility functions to complex microservices and streaming pipelines.

To get the best results, always include context (framework, library, language version), specify error handling, and mention edge cases. As AI models continue to improve, the ability to write precise prompts will become an increasingly valuable skill for developers. Experiment with these prompts, adapt them to your projects, and remember to review and test the generated code before deployment.

For further learning, explore official documentation for TypeScript, React, and Node.js, and consider contributing to open-source projects where prompt-assisted code generation can help with repetitive tasks.

← All posts

Comments