10 Prompts for JavaScript and TypeScript Code Generation: React, Node.js, and Utility Patterns

Introduction

Generating code with AI assistants has become a daily practice for many developers. When working with JavaScript and TypeScript, well-crafted prompts can save hours of boilerplate writing and debugging. This article collects 10 battle-tested prompts for common JS/TS tasks—from React components and Node.js endpoints to type-safe utility functions. Each prompt follows a consistent structure: a clear task, the exact prompt text, and a real-world output example. Whether you are new to prompt engineering or looking to refine your current templates, these patterns will help you get consistent, production-ready code.

10 Prompts for JavaScript & TypeScript Code Generation

1. React Functional Component with TypeScript Props (Basic)

Task – Create a reusable React component that accepts typed props and renders a styled card.

Prompt

Generate a React functional component in TypeScript called `ProductCard`. 
It should accept props: { product: { id: number; name: string; price: number; imageUrl: string } }. 
Display the image, name, and price. Use Tailwind CSS classes for styling. 
Include a simple hover effect and make the card clickable (onClick prop).
Export as default.

Example Result

import React from 'react';

interface Product {
  id: number;
  name: string;
  price: number;
  imageUrl: string;
}

interface ProductCardProps {
  product: Product;
  onClick?: (product: Product) => void;
}

const ProductCard: React.FC<ProductCardProps> = ({ product, onClick }) => {
  return (
    <div
      className="max-w-sm rounded overflow-hidden shadow-lg cursor-pointer transition-transform hover:scale-105"
      onClick={() => onClick?.(product)}
    >
      <img className="w-full h-48 object-cover" src={product.imageUrl} alt={product.name} />
      <div className="px-6 py-4">
        <div className="font-bold text-xl mb-2">{product.name}</div>
        <p className="text-gray-700 text-base">${product.price.toFixed(2)}</p>
      </div>
    </div>
  );
};

export default ProductCard;

2. Generic Array Utility (TypeScript – Intermediate)

Task – Write a type-safe function that groups an array by a key derived from each element.

Prompt

Create a TypeScript function called `groupBy<T, K extends string | number>(
  array: T[],
  keyGetter: (item: T) => K
): Record<K, T[]>`.
It should return an object where keys are the result of keyGetter and values are arrays of matching items.
Include a simple JSDoc comment. Do not use external libraries.

Example Result

type GroupBy = <T, K extends string | number>(
  array: T[],
  keyGetter: (item: T) => K
) => Record<K, T[]>;

const groupBy: GroupBy = (array, keyGetter) => {
  return array.reduce((acc, item) => {
    const key = keyGetter(item);
    if (!acc[key]) {
      acc[key] = [];
    }
    acc[key].push(item);
    return acc;
  }, {} as Record<K, T[]>);
};

// Usage example:
// const grouped = groupBy([{ type: 'a' }, { type: 'b' }], (x) => x.type);

3. Express.js Middleware for Authentication (Node.js – Advanced)

Task – Build a JWT verification middleware in Node.js using Express and TypeScript.

Prompt

Write an Express middleware function in TypeScript called `authenticate`.
It should extract a JWT from the Authorization header (Bearer scheme),
verify it using jsonwebtoken with a secret from env variable `JWT_SECRET`,
and attach the decoded payload to `req.user`. If the token is missing or invalid,
respond with 401 and a JSON error message. Use async/await.
Also provide a custom Request type augmentation.

Example Result

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

declare global {
  namespace Express {
    interface Request {
      user?: { id: string; role: string };
    }
  }
}

interface JwtPayload {
  id: string;
  role: string;
}

export const authenticate = async (
  req: Request,
  res: Response,
  next: NextFunction
): Promise<void> => {
  try {
    const authHeader = req.headers.authorization;
    if (!authHeader || !authHeader.startsWith('Bearer ')) {
      res.status(401).json({ error: 'Missing or malformed token' });
      return;
    }

    const token = authHeader.split(' ')[1];
    const secret = process.env.JWT_SECRET || 'fallback_secret';
    const decoded = jwt.verify(token, secret) as JwtPayload;

    req.user = { id: decoded.id, role: decoded.role };
    next();
  } catch (error) {
    res.status(401).json({ error: 'Invalid or expired token' });
  }
};

4. Custom React Hook for Debounced State (React – Advanced)

Task – Implement a custom hook that returns a debounced value.

Prompt

Create a generic React hook `useDebounce<T>(value: T, delay: number): T`.
It should return the debounced value that updates only after `delay` milliseconds
of no changes. Use `useState` and `useEffect` with cleanup.
The hook must be typed correctly. Provide a brief usage example.

Example Result

import { useState, useEffect } from 'react';

function useDebounce<T>(value: T, delay: number): T {
  const [debouncedValue, setDebouncedValue] = useState<T>(value);

  useEffect(() => {
    const timer = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);

    return () => {
      clearTimeout(timer);
    };
  }, [value, delay]);

  return debouncedValue;
}

// Usage in a search component:
// const [searchTerm, setSearchTerm] = useState('');
// const debouncedSearch = useDebounce(searchTerm, 300);

5. Zod Schema & Type Inference (Expert – TypeScript)

Task – Define a validation schema with Zod and derive the TypeScript type.

Prompt

Using the Zod library (v3), create a schema for a user registration payload:
- email: string, must be a valid email
- password: string, min 8 characters, max 64
- age: optional number, must be between 13 and 120
Then infer the TypeScript type from the schema using `z.infer`.
Export both the schema and the type. Also write a validation function that returns the parsed data or throws a friendly error.

Example Result

import { z } from 'zod';

export const UserRegistrationSchema = z.object({
  email: z.string().email(),
  password: z.string().min(8).max(64),
  age: z.number().min(13).max(120).optional(),
});

export type UserRegistration = z.infer<typeof UserRegistrationSchema>;

export function validateUserRegistration(data: unknown): UserRegistration {
  const result = UserRegistrationSchema.safeParse(data);
  if (!result.success) {
    throw new Error(
      `Validation failed: ${result.error.issues
        .map((issue) => `${issue.path.join('.')}: ${issue.message}`)
        .join(', ')}`
    );
  }
  return result.data;
}

6. Async Queue with Concurrency Control (Expert – Node.js)

Task – Write a class that processes tasks with a maximum number of concurrent executions.

Prompt

Implement a TypeScript class `AsyncQueue<T, R>` with methods:
- `add(task: () => Promise<T>): Promise<R>` – enqueues a task and returns a promise that resolves with the task result.
- `pause()` – stops processing new tasks.
- `resume()` – continues processing.
The constructor should accept `concurrency: number` (default 2).
Use a queue (FIFO) and manage a running count. 
Handle errors per task without crashing the queue.

Example Result

type Task<T> = () => Promise<T>;

class AsyncQueue<T, R = T> {
  private queue: { task: Task<T>; resolve: (value: R) => void; reject: (reason?: any) => void }[] = [];
  private running = 0;
  private paused = false;
  private concurrency: number;

  constructor(concurrency = 2) {
    this.concurrency = concurrency;
  }

  add(task: Task<T>): Promise<R> {
    return new Promise((resolve, reject) => {
      this.queue.push({ task, resolve: resolve as (value: R) => void, reject });
      this.processNext();
    });
  }

  pause(): void {
    this.paused = true;
  }

  resume(): void {
    this.paused = false;
    this.processNext();
  }

  private async processNext(): Promise<void> {
if (this.paused

|| this.running >= this.concurrency || this.queue.length === 0) return;

    this.running++;
    const { task, resolve, reject } = this.queue.shift()!;

    try {
      const result = await task();
      resolve(result as unknown as R);
    } catch (error) {
      reject(error);
    } finally {
      this.running--;
      this.processNext();
    }
  }
}

export default AsyncQueue;

7. React Context with useReducer (Intermediate – React)

Task – Build a type-safe authentication context using useReducer.

Prompt

Create an AuthContext in React with TypeScript using useReducer. 
State: { user: User

| null; loading: boolean; error: string | null }.
Actions: LOGIN_START, LOGIN_SUCCESS, LOGIN_FAILURE, LOGOUT.
Provide a custom hook `useAuth` that throws if used outside the provider.
The User type should have id, email, name.
Export AuthProvider, useAuth, and the action creators.

Example Result

import React, { createContext, useContext, useReducer, ReactNode } from 'react';

interface User {
  id: string;
  email: string;
  name: string;
}

interface AuthState {
  user: User | null;
  loading: boolean;
  error: string | null;
}

type AuthAction =
  | { type: 'LOGIN_START' }
  | { type: 'LOGIN_SUCCESS'; payload: User }
  | { type: 'LOGIN_FAILURE'; payload: string }
  | { type: 'LOGOUT' };

const initialState: AuthState = { user: null, loading: false, error: null };

function authReducer(state: AuthState, action: AuthAction): AuthState {
  switch (action.type) {
    case 'LOGIN_START':
      return { ...state, loading: true, error: null };
    case 'LOGIN_SUCCESS':
      return { user: action.payload, loading: false, error: null };
    case 'LOGIN_FAILURE':
      return { user: null, loading: false, error: action.payload };
    case 'LOGOUT':
      return initialState;
    default:
      return state;
  }
}

interface AuthContextValue {
  state: AuthState;
  dispatch: React.Dispatch<AuthAction>;
}

const AuthContext = createContext<AuthContextValue | undefined>(undefined);

export function AuthProvider({ children }: { children: ReactNode }) {
  const [state, dispatch] = useReducer(authReducer, initialState);
  return (
    <AuthContext.Provider value={{ state, dispatch }}>
      {children}
    </AuthContext.Provider>
  );
}

export function useAuth() {
  const context = useContext(AuthContext);
  if (!context) {
    throw new Error('useAuth must be used within an AuthProvider');
  }
  return context;
}

export const loginStart = () => ({ type: 'LOGIN_START' } as const);
export const loginSuccess = (user: User) => ({ type: 'LOGIN_SUCCESS', payload: user } as const);
export const loginFailure = (error: string) => ({ type: 'LOGIN_FAILURE', payload: error } as const);
export const logout = () => ({ type: 'LOGOUT' } as const);

8. TypeScript Mapped Type for API Responses (Advanced)

Task – Define a generic wrapper type that adds pagination metadata.

Prompt

Create a TypeScript type `PaginatedResponse<T>` that wraps an array of items
and includes `page`, `pageSize`, `totalItems`, `totalPages`.
Then write a type `ApiResponse<T>` that can be either `{ success: true; data: T }`
or `{ success: false; error: string }`.
Finally, combine them to form `PaginatedApiResponse<T>` using intersections.
Provide a usage example with a mock fetch function.

Example Result

type PaginatedResponse<T> = {
  items: T[];
  page: number;
  pageSize: number;
  totalItems: number;
  totalPages: number;
};

type ApiResponse<T> =
  | { success: true; data: T }
  | { success: false; error: string };

type PaginatedApiResponse<T> = ApiResponse<PaginatedResponse<T>>;

// Usage:
const mockFetchUsers = async (page: number): Promise<PaginatedApiResponse<{ id: number; name: string }>> => {
  return {
    success: true,
    data: {
      items: [{ id: 1, name: 'Alice' }],
      page,
      pageSize: 10,
      totalItems: 1,
      totalPages: 1,
    },
  };
};

9. Node.js Stream Processing for Large Files (Expert)

Task – Write a utility that reads a large CSV file line by line, transforms data, and writes a new CSV, using streams.

Prompt

Create a Node.js script using `fs.createReadStream`, `readline`, and `fs.createWriteStream`.
It should read a large CSV file (path as argument), filter rows where column `age` > 18,
and write the filtered rows to an output file. Use TypeScript with proper types.
Assume CSV has headers. Handle backpressure. Do not use external libraries.

Example Result

import fs from 'fs';
import readline from 'readline';

async function filterCSV(
  inputPath: string,
  outputPath: string,
  column: string,
  predicate: (value: string) => boolean
): Promise<void> {
  const readStream = fs.createReadStream(inputPath, { encoding: 'utf-8' });
  const writeStream = fs.createWriteStream(outputPath);
  const rl = readline.createInterface({ input: readStream, crlfDelay: Infinity });

  let headers: string[] = [];
  let columnIndex = -1;

  return new Promise((resolve, reject) => {
    rl.on('line', (line) => {
      if (headers.length === 0) {
        headers = line.split(',');
        columnIndex = headers.indexOf(column);
        if (columnIndex === -1) {
          rl.close();
          reject(new Error(`Column "${column}" not found`));
          return;
        }
        writeStream.write(line + '\n');
      } else {
        const values = line.split(',');
        const cell = values[columnIndex];
        if (predicate(cell)) {
          writeStream.write(line + '\n');
        }
      }
    });

    rl.on('close', () => {
      writeStream.end();
      resolve();
    });

    rl.on('error', reject);
    writeStream.on('error', reject);
  });
}

// Usage:
// filterCSV('input.csv', 'output.csv', 'age', (val) => parseInt(val) > 18);

10. Builder Pattern for Complex Objects (TypeScript – Expert)

Task – Implement a type-safe builder for constructing SQL SELECT queries.

Prompt

Write a TypeScript class `QueryBuilder` that uses method chaining to build a SELECT query.
Methods: `select(...columns: string[])`, `from(table: string)`, `where(condition: string)`,
`orderBy(column: string, direction?: 'ASC' | 'DESC')`.
The `build()` method should return the final SQL string.
Use a generic type parameter to track selected columns for compile-time safety (optional).
Protect against SQL injection by not allowing raw user input in `.where()`—use parameterized placeholders.

Example Result

class QueryBuilder {
  private columns: string[] = ['*'];
  private table: string = '';
  private whereClauses: string[] = [];
  private orderColumn: string = '';
  private orderDir: 'ASC' | 'DESC' = 'ASC';

  select(...cols: string[]): this {
    this.columns = cols;
    return this;
  }

  from(table: string): this {
    this.table = table;
    return this;
  }

  where(condition: string, params?: Record<string, any>): this {
    // In a full implementation, params would be stored for parameterized query
    this.whereClauses.push(condition);
    return this;
  }

  orderBy(column: string, direction: 'ASC' | 'DESC' = 'ASC'): this {
    this.orderColumn = column;
    this.orderDir = direction;
    return this;
  }

  build(): string {
    if (!this.table) throw new Error('Table not set');
    let sql = `SELECT ${this.columns.join(', ')} FROM ${this.table}`;
    if (this.whereClauses.length > 0) {
      sql += ` WHERE ${this.whereClauses.join(' AND ')}`;
    }
    if (this.orderColumn) {
      sql += ` ORDER BY ${this.orderColumn} ${this.orderDir}`;
    }
    return sql;
  }
}

// Usage:
// const query = new QueryBuilder()
//   .select('id', 'name', 'email')
//   .from('users')
//   .where('age > :minAge', { minAge: 18 })
//   .orderBy('name', 'ASC')
//   .build();

Conclusion

These 10 prompts cover a wide spectrum of JavaScript and TypeScript code generation—from simple React components to advanced async queues and type-safe builders. By feeding these detailed prompts to your AI assistant, you can produce consistent, production-ready code that follows best practices. The key is to be specific: include types, error handling, edge cases, and style preferences. Experiment with your own variations and adjust the wording to match your project’s conventions. Remember that prompt engineering is an iterative process—review the output, tweak the instructions, and re-run until the generated code meets your standards.

Start using these prompts today and cut down the time spent on boilerplate. Share your own favorite prompts in the comments!

← All posts

Comments