Smithery Logo
MCPsSkillsDocsPricing
Login
Smithery Logo

Give agents more agency

Resources

DocumentationPrivacy PolicySystem Status

Company

PricingAboutBlog

Connect

© 2026 Smithery. All rights reserved.

    kivo360

    moai-lang-typescript

    kivo360/moai-lang-typescript
    Coding
    1

    About

    SKILL.md

    Install

    • Telegram
      Telegram
    • Slack
      Slack
    • Claude Code
      Claude Code
    • Codex
      Codex
    • OpenClaw
      OpenClaw
    • Cursor
      Cursor
    • Amp
      Amp
    • GitHub Copilot
      GitHub Copilot
    • Gemini CLI
      Gemini CLI
    • Kilo Code
      Kilo Code
    • Junie
      Junie
    • Replit
      Replit
    • Windsurf
      Windsurf
    • Cline
      Cline
    • Continue
      Continue
    • OpenCode
      OpenCode
    • OpenHands
      OpenHands
    • Roo Code
      Roo Code
    • Augment
      Augment
    • Goose
      Goose
    • Trae
      Trae
    • Zencoder
      Zencoder
    • Antigravity
      Antigravity
    • Download skill
    ├─
    ├─
    └─

    About

    TypeScript best practices with modern frameworks, full-stack development, and type-safe patterns for 2025

    SKILL.md

    TypeScript Development Mastery

    Modern TypeScript Development with 2025 Best Practices

    Comprehensive TypeScript development guidance covering full-stack applications, type-safe patterns, modern frameworks, and production-ready code using the latest tools and methodologies.

    What It Does

    • Full-Stack Development: Next.js, React, Node.js with end-to-end type safety
    • Type-Safe APIs: REST and GraphQL with TypeScript validation
    • Modern Frontend: React 19+, Vue 3+, Angular 17+ with TypeScript
    • Backend Services: Node.js, Deno, Bun with TypeScript optimization
    • Testing Strategies: Vitest, Jest, Playwright with type-safe testing
    • Build & Deployment: Modern bundlers, CI/CD, performance optimization
    • Code Quality: ESLint, Prettier, automated type checking
    • Enterprise Patterns: Monorepos, microservices, scalable architecture

    When to Use

    Perfect Scenarios

    • Building full-stack web applications
    • Developing type-safe APIs and microservices
    • Creating modern React/Next.js applications
    • Enterprise-scale JavaScript applications
    • Projects requiring strict type safety
    • Teams with multiple JavaScript skill levels
    • Applications with complex data models

    Common Triggers

    • "Create TypeScript API"
    • "Set up Next.js project"
    • "Type-safe React components"
    • "TypeScript best practices"
    • "Migrate JavaScript to TypeScript"
    • "Full-stack TypeScript application"

    Tool Version Matrix (2025-11-06)

    Core TypeScript

    • TypeScript: 5.6.x (latest) / 5.3.x (LTS)
    • Node.js: 22.x (LTS) / 20.x (stable)
    • Package Managers: pnpm 9.x, npm 10.x, yarn 4.x
    • Runtimes: Node.js 22.x, Deno 2.x, Bun 1.1.x

    Frontend Frameworks

    • Next.js: 15.x - Full-stack React framework
    • React: 19.x - UI library with Server Components
    • Vue: 3.5.x - Progressive framework
    • Angular: 18.x - Enterprise framework
    • Svelte: 5.x - Compiler-based framework

    Build Tools

    • Vite: 6.x - Fast build tool
    • Webpack: 5.x - Module bundler
    • esbuild: 0.24.x - Fast bundler
    • SWC: 1.7.x - Rust-based compiler

    Testing Tools

    • Vitest: 2.x - Fast unit testing
    • Jest: 30.x - Comprehensive testing
    • Playwright: 1.48.x - E2E testing
    • Testing Library: 16.x - Component testing

    Code Quality

    • ESLint: 9.x - Linting (flat config)
    • Prettier: 3.3.x - Code formatting
    • TypeScript Compiler: Built-in type checking
    • Husky: 9.x - Git hooks

    Backend Frameworks

    • Express: 4.21.x - Minimal web framework
    • Fastify: 5.x - Fast web framework
    • NestJS: 10.x - Enterprise framework
    • tRPC: 11.x - End-to-end typesafe APIs

    Ecosystem Overview

    Project Setup (2025 Best Practice)

    # Modern TypeScript with pnpm (recommended)
    pnpm create next-app@latest my-app --typescript --tailwind --eslint --app
    cd my-app
    pnpm add @types/node @types/react @types/react-dom
    pnpm add -D vitest @vitest/ui jsdom @testing-library/react
    
    # Alternative: Bun for ultra-fast development
    bun create next-app my-app
    cd my-app
    bun add vitest @testing-library/react -d
    
    # Monorepo with Nx or Turborepo
    npx create-nx-workspace@latest my-workspace --preset=react-monorepo
    # or
    npx create-turbo@latest my-turbo-app
    

    Modern Project Structure

    my-typescript-project/
    ├── package.json
    ├── tsconfig.json              # TypeScript configuration
    ├── tsconfig.build.json        # Build-specific config
    ├── vite.config.ts             # Build tool configuration
    ├── eslint.config.js           # ESLint flat config
    ├── prettier.config.js         # Prettier configuration
    ├── playwright.config.ts       # E2E testing config
    ├── vitest.config.ts           # Unit testing config
    ├── src/
    │   ├── app/                   # Next.js app router
    │   │   ├── layout.tsx
    │   │   ├── page.tsx
    │   │   ├── globals.css
    │   │   └── api/               # API routes
    │   ├── components/            # Reusable components
    │   │   ├── ui/                # UI components
    │   │   └── features/          # Feature components
    │   ├── lib/                   # Utilities and configs
    │   │   ├── utils.ts
    │   │   ├── db.ts              # Database configuration
    │   │   └── types.ts           # Global type definitions
    │   ├── hooks/                 # Custom React hooks
    │   └── types/                 # Domain-specific types
    ├── tests/
    │   ├── __mocks__/             # Mock files
    │   ├── setup.ts               # Test setup
    │   └── integration/           # Integration tests
    └── .github/
        └── workflows/             # CI/CD pipelines
    

    Modern TypeScript Patterns

    Advanced Type System Features (TypeScript 5.6)

    // Import attributes for better module management
    import data from "./data.json" with { type: "json" };
    
    // Template literal type improvements
    type EventName<T extends string> = `on${Capitalize<T>}`;
    type UserEvent = EventName<'click' | 'hover'>; // 'onClick' | 'onHover'
    
    // Enhanced symbol key handling
    const metaKey = Symbol('metadata');
    interface Metadata {
      [metaKey]: string;
    }
    
    // Improved decorator metadata
    function Entity<T extends { new(...args: any[]): {} }>(constructor: T) {
      return class extends constructor {
        createdAt = new Date();
      };
    }
    
    @Entity
    class User {
      constructor(public name: string) {}
    }
    

    Utility Types and Patterns

    // Advanced utility types
    type StrictOmit<T, K extends keyof T> = T extends Record<string, unknown>
      ? Pick<T, Exclude<keyof T, K>>
      : never;
    
    type DeepPartial<T> = {
      [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
    };
    
    type Branded<T, B> = T & { __brand: B };
    
    // Type-safe IDs
    type UserId = Branded<string, 'UserId'>;
    type ProductId = Branded<string, 'ProductId'>;
    
    function createUserId(id: string): UserId {
      return id as UserId;
    }
    
    // Type-safe API client
    type ApiResponse<T, E = unknown> = 
      | { success: true; data: T }
      | { success: false; error: E };
    
    interface User {
      id: UserId;
      name: string;
      email: string;
    }
    
    async function fetchUser(id: UserId): Promise<ApiResponse<User>> {
      try {
        const response = await fetch(`/api/users/${id}`);
        if (!response.ok) throw new Error('Failed to fetch');
        const data = await response.json();
        return { success: true, data };
      } catch (error) {
        return { success: false, error };
      }
    }
    

    React Patterns with TypeScript

    // Type-safe component props with forwardRef
    import React, { forwardRef, useImperativeHandle } from 'react';
    
    interface ButtonProps {
      variant: 'primary' | 'secondary' | 'danger';
      size: 'sm' | 'md' | 'lg';
      disabled?: boolean;
      children: React.ReactNode;
      onClick?: () => void;
    }
    
    export interface ButtonRef {
      click: () => void;
      focus: () => void;
    }
    
    export const Button = forwardRef<ButtonRef, ButtonProps>(
      ({ variant, size, disabled, children, onClick }, ref) => {
        const buttonRef = React.useRef<HTMLButtonElement>(null);
    
        useImperativeHandle(ref, () => ({
          click: () => buttonRef.current?.click(),
          focus: () => buttonRef.current?.focus(),
        }));
    
        const baseClasses = 'font-semibold rounded-lg transition-colors';
        const variantClasses = {
          primary: 'bg-blue-600 text-white hover:bg-blue-700',
          secondary: 'bg-gray-200 text-gray-900 hover:bg-gray-300',
          danger: 'bg-red-600 text-white hover:bg-red-700',
        };
        const sizeClasses = {
          sm: 'px-3 py-1 text-sm',
          md: 'px-4 py-2 text-base',
          lg: 'px-6 py-3 text-lg',
        };
    
        return (
          <button
            ref={buttonRef}
            className={`${baseClasses} ${variantClasses[variant]} ${sizeClasses[size]}`}
            disabled={disabled}
            onClick={onClick}
          >
            {children}
          </button>
        );
      }
    );
    
    Button.displayName = 'Button';
    

    Custom Hooks with TypeScript

    // Type-safe data fetching hook
    interface UseApiResult<T, E = unknown> {
      data: T | null;
      error: E | null;
      loading: boolean;
      refetch: () => Promise<void>;
    }
    
    function useApi<T, E = unknown>(
      url: string,
      options?: RequestInit
    ): UseApiResult<T, E> {
      const [data, setData] = React.useState<T | null>(null);
      const [error, setError] = React.useState<E | null>(null);
      const [loading, setLoading] = React.useState(false);
    
      const fetchData = React.useCallback(async () => {
        setLoading(true);
        setError(null);
        
        try {
          const response = await fetch(url, options);
          if (!response.ok) throw new Error(response.statusText);
          const result = await response.json() as T;
          setData(result);
        } catch (err) {
          setError(err as E);
        } finally {
          setLoading(false);
        }
      }, [url, options]);
    
      React.useEffect(() => {
        fetchData();
      }, [fetchData]);
    
      return { data, error, loading, refetch: fetchData };
    }
    
    // Usage
    interface User {
      id: number;
      name: string;
      email: string;
    }
    
    function UserProfile({ userId }: { userId: number }) {
      const { data: user, loading, error } = useApi<User>(`/api/users/${userId}`);
    
      if (loading) return <div>Loading...</div>;
      if (error) return <div>Error: {error.message}</div>;
      if (!user) return <div>No user found</div>;
    
      return (
        <div>
          <h1>{user.name}</h1>
          <p>{user.email}</p>
        </div>
      );
    }
    

    Performance Optimization

    Code Splitting and Lazy Loading

    // Dynamic imports with type safety
    import { lazy, Suspense } from 'react';
    
    const HeavyComponent = lazy(() => 
      import('./HeavyComponent').then(module => ({
        default: module.HeavyComponent
      }))
    );
    
    // Route-based code splitting
    import { createBrowserRouter } from 'react-router-dom';
    
    const router = createBrowserRouter([
      {
        path: '/',
        element: <HomePage />,
      },
      {
        path: '/dashboard',
        element: (
          <Suspense fallback={<div>Loading dashboard...</div>}>
            <LazyDashboard />
          </Suspense>
        ),
        loader: () => import('./loaders/dashboardLoader').then(m => m.dashboardLoader()),
      },
    ]);
    
    // Preloading strategies
    const preloadComponent = () => {
      import('./HeavyComponent');
    };
    
    // Preload on hover
    <button onMouseEnter={preloadComponent}>
      Load Component
    </button>
    

    Bundle Optimization

    // vite.config.ts - Modern build configuration
    import { defineConfig } from 'vite';
    import react from '@vitejs/plugin-react-swc';
    import { visualizer } from 'rollup-plugin-visualizer';
    
    export default defineConfig({
      plugins: [
        react(),
        process.env.ANALYZE && visualizer({
          filename: 'dist/stats.html',
          open: true,
        }),
      ],
      build: {
        rollupOptions: {
          output: {
            manualChunks: {
              vendor: ['react', 'react-dom'],
              router: ['react-router-dom'],
              ui: ['@radix-ui/react-dialog', '@radix-ui/react-dropdown-menu'],
            },
          },
        },
        chunkSizeWarningLimit: 1000,
      },
      server: {
        hmr: {
          overlay: true,
        },
      },
    });
    

    Memory Management

    // Efficient state management with useReducer
    interface State {
      items: Item[];
      filter: string;
      loading: boolean;
    }
    
    type Action =
      | { type: 'SET_ITEMS'; payload: Item[] }
      | { type: 'SET_FILTER'; payload: string }
      | { type: 'SET_LOADING'; payload: boolean };
    
    function itemsReducer(state: State, action: Action): State {
      switch (action.type) {
        case 'SET_ITEMS':
          return { ...state, items: action.payload, loading: false };
        case 'SET_FILTER':
          return { ...state, filter: action.payload };
        case 'SET_LOADING':
          return { ...state, loading: action.payload };
        default:
          return state;
      }
    }
    
    // Memoized components for performance
    import { memo, useMemo, useCallback } from 'react';
    
    interface ExpensiveComponentProps {
      data: number[];
      onItemClick: (id: number) => void;
    }
    
    const ExpensiveComponent = memo<ExpensiveComponentProps>(({ data, onItemClick }) => {
      const processedData = useMemo(() => {
        return data.map(item => ({
          ...item,
          processed: expensiveCalculation(item),
        }));
      }, [data]);
    
      const handleClick = useCallback((id: number) => {
        onItemClick(id);
      }, [onItemClick]);
    
      return (
        <div>
          {processedData.map(item => (
            <Item key={item.id} item={item} onClick={handleClick} />
          ))}
        </div>
      );
    });
    

    Testing Strategies

    Vitest Configuration

    // vitest.config.ts
    import { defineConfig } from 'vitest/config';
    import react from '@vitejs/plugin-react-swc';
    import path from 'path';
    
    export default defineConfig({
      plugins: [react()],
      test: {
        globals: true,
        environment: 'jsdom',
        setupFiles: ['./tests/setup.ts'],
        coverage: {
          provider: 'v8',
          reporter: ['text', 'json', 'html'],
          exclude: [
            'node_modules/',
            'tests/',
            '**/*.d.ts',
            '**/*.config.*',
            'dist/',
          ],
        },
      },
      resolve: {
        alias: {
          '@': path.resolve(__dirname, './src'),
        },
      },
    });
    

    Type-Safe Testing Patterns

    // Component testing with Testing Library
    import { render, screen, fireEvent, waitFor } from '@testing-library/react';
    import { vi, type MockedFunction } from 'vitest';
    import { Button } from './Button';
    
    describe('Button', () => {
      it('renders with correct variant styles', () => {
        render(
          <Button variant="primary" size="md" onClick={vi.fn()}>
            Click me
          </Button>
        );
    
        const button = screen.getByRole('button', { name: 'Click me' });
        expect(button).toBeInTheDocument();
        expect(button).toHaveClass('bg-blue-600', 'text-white');
      });
    
      it('handles click events', async () => {
        const handleClick = vi.fn();
        render(
          <Button variant="secondary" size="sm" onClick={handleClick}>
            Submit
          </Button>
        );
    
        const button = screen.getByRole('button', { name: 'Submit' });
        fireEvent.click(button);
    
        expect(handleClick).toHaveBeenCalledTimes(1);
      });
    
      it('can be triggered via ref', () => {
        const handleClick = vi.fn();
        const ref = { current: null };
    
        render(
          <Button variant="primary" size="md" onClick={handleClick} ref={ref}>
            Click via ref
          </Button>
        );
    
        // TypeScript should infer the correct ref type
        if (ref.current) {
          ref.current.click();
        }
    
        expect(handleClick).toHaveBeenCalledTimes(1);
      });
    });
    
    // API testing with MSW
    import { rest } from 'msw';
    import { setupServer } from 'msw/node';
    import { fetchUser } from './api';
    
    const server = setupServer(
      rest.get('/api/users/1', (req, res, ctx) => {
        return res(
          ctx.json({
            id: 1,
            name: 'John Doe',
            email: 'john@example.com',
          })
        );
      })
    );
    
    beforeAll(() => server.listen());
    afterEach(() => server.resetHandlers());
    afterAll(() => server.close());
    
    describe('fetchUser', () => {
      it('fetches user data successfully', async () => {
        const userId = createUserId('1');
        const result = await fetchUser(userId);
    
        if (result.success) {
          expect(result.data.name).toBe('John Doe');
          expect(result.data.email).toBe('john@example.com');
        } else {
          fail('Expected successful fetch');
        }
      });
    });
    

    E2E Testing with Playwright

    // tests/e2e/user-journey.spec.ts
    import { test, expect, type Page } from '@playwright/test';
    
    test.describe('User Authentication Flow', () => {
      test('should allow user to sign up and log in', async ({ page }) => {
        // Sign up
        await page.goto('/signup');
        
        await page.fill('[data-testid=email-input]', 'user@example.com');
        await page.fill('[data-testid=password-input]', 'securepassword123');
        await page.fill('[data-testid=name-input]', 'Test User');
        
        await page.click('[data-testid=signup-button]');
        
        // Should redirect to dashboard
        await expect(page).toHaveURL('/dashboard');
        await expect(page.locator('[data-testid=user-name]')).toHaveText('Test User');
        
        // Log out
        await page.click('[data-testid=logout-button]');
        
        // Log in
        await page.goto('/login');
        await page.fill('[data-testid=email-input]', 'user@example.com');
        await page.fill('[data-testid=password-input]', 'securepassword123');
        await page.click('[data-testid=login-button]');
        
        // Should be back at dashboard
        await expect(page).toHaveURL('/dashboard');
      });
    
      test('should show validation errors for invalid input', async ({ page }) => {
        await page.goto('/signup');
        
        // Try to submit with empty fields
        await page.click('[data-testid=signup-button]');
        
        await expect(page.locator('[data-testid=email-error]')).toBeVisible();
        await expect(page.locator('[data-testid=password-error]')).toBeVisible();
        await expect(page.locator('[data-testid=name-error]')).toBeVisible();
      });
    });
    

    Security Best Practices

    Input Validation and Sanitization

    // Type-safe validation with Zod
    import { z } from 'zod';
    
    const UserSchema = z.object({
      name: z.string().min(1).max(100).trim(),
      email: z.string().email(),
      age: z.number().min(13).max(120),
      bio: z.string().max(1000).optional(),
    });
    
    type User = z.infer<typeof UserSchema>;
    
    // API route validation
    export async function POST(request: Request) {
      try {
        const body = await request.json();
        const validatedUser = UserSchema.parse(body);
        
        // Process validated data
        await createUser(validatedUser);
        
        return Response.json({ success: true }, { status: 201 });
      } catch (error) {
        if (error instanceof z.ZodError) {
          return Response.json(
            { 
              success: false, 
              errors: error.flatten().fieldErrors 
            },
            { status: 400 }
          );
        }
        
        return Response.json(
          { success: false, error: 'Internal server error' },
          { status: 500 }
        );
      }
    }
    
    // XSS prevention
    function sanitizeHtml(input: string): string {
      // Use DOMPurify or similar library
      return input.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '');
    }
    
    // CSRF protection
    function getCSRFToken(): string {
      const meta = document.querySelector('meta[name="csrf-token"]');
      return meta?.getAttribute('content') || '';
    }
    
    // Secure API client
    class SecureApiClient {
      private baseUrl: string;
      private csrfToken: string;
    
      constructor(baseUrl: string) {
        this.baseUrl = baseUrl;
        this.csrfToken = getCSRFToken();
      }
    
      async post<T>(endpoint: string, data: unknown): Promise<T> {
        const response = await fetch(`${this.baseUrl}${endpoint}`, {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            'X-CSRF-Token': this.csrfToken,
          },
          body: JSON.stringify(data),
        });
    
        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`);
        }
    
        return response.json() as Promise<T>;
      }
    }
    

    Authentication and Authorization

    // JWT-based authentication
    interface JWTPayload {
      userId: string;
      email: string;
      role: 'user' | 'admin';
      exp: number;
    }
    
    class AuthService {
      private static readonly TOKEN_KEY = 'auth_token';
    
      static setToken(token: string): void {
        localStorage.setItem(this.TOKEN_KEY, token);
      }
    
      static getToken(): string | null {
        return localStorage.getItem(this.TOKEN_KEY);
      }
    
      static removeToken(): void {
        localStorage.removeItem(this.TOKEN_KEY);
      }
    
      static isTokenExpired(token: string): boolean {
        try {
          const payload = JSON.parse(atob(token.split('.')[1])) as JWTPayload;
          return Date.now() >= payload.exp * 1000;
        } catch {
          return true;
        }
      }
    
      static getCurrentUser(): JWTPayload | null {
        const token = this.getToken();
        if (!token || this.isTokenExpired(token)) {
          return null;
        }
    
        try {
          return JSON.parse(atob(token.split('.')[1])) as JWTPayload;
        } catch {
          return null;
        }
      }
    }
    
    // Protected routes
    interface ProtectedRouteProps {
      children: React.ReactNode;
      requiredRole?: 'user' | 'admin';
    }
    
    function ProtectedRoute({ children, requiredRole = 'user' }: ProtectedRouteProps) {
      const user = AuthService.getCurrentUser();
      
      if (!user) {
        return <Navigate to="/login" replace />;
      }
    
      if (requiredRole === 'admin' && user.role !== 'admin') {
        return <Navigate to="/unauthorized" replace />;
      }
    
      return <>{children}</>;
    }
    
    // API middleware
    function withAuth<T extends unknown[], R>(
      handler: (...args: T) => Promise<R>
    ) {
      return async (...args: T): Promise<R> => {
        const token = AuthService.getToken();
        
        if (!token || AuthService.isTokenExpired(token)) {
          throw new Error('Unauthorized');
        }
    
        return handler(...args);
      };
    }
    

    Integration Patterns

    Full-Stack Type Safety with tRPC

    // server/router.ts
    import { initTRPC } from '@trpc/server';
    import { z } from 'zod';
    import type { CreateHTTPContextOptions } from '@trpc/server/adapters/standalone';
    
    const t = initTRPC.context<CreateHTTPContextOptions>().create();
    
    export const appRouter = t.router({
      getUser: t.procedure
        .input(z.object({ id: z.string() }))
        .query(async ({ input, ctx }) => {
          const user = await ctx.db.user.findUnique({
            where: { id: input.id },
          });
          return user;
        }),
        
      createUser: t.procedure
        .input(z.object({
          name: z.string().min(1),
          email: z.string().email(),
        }))
        .mutation(async ({ input, ctx }) => {
          const user = await ctx.db.user.create({
            data: input,
          });
          return user;
        }),
    });
    
    export type AppRouter = typeof appRouter;
    
    // client/trpc.ts
    import { createTRPCProxyClient, httpBatchLink } from '@trpc/client';
    import type { AppRouter } from '../server/router';
    
    const trpc = createTRPCProxyClient<AppRouter>({
      links: [
        httpBatchLink({
          url: 'http://localhost:3000/trpc',
        }),
      ],
    });
    
    // Usage in React component
    function UserProfile({ userId }: { userId: string }) {
      const { data: user, isLoading } = trpc.getUser.useQuery({ id: userId });
      const createUser = trpc.createUser.useMutation();
    
      if (isLoading) return <div>Loading...</div>;
    
      return (
        <div>
          <h1>{user?.name}</h1>
          <p>{user?.email}</p>
          <button 
            onClick={() => createUser.mutate({
              name: 'New User',
              email: 'new@example.com',
            })}
          >
            Create User
          </button>
        </div>
      );
    }
    

    Database Integration with Prisma

    // schema.prisma
    model User {
      id        String   @id @default(cuid())
      email     String   @unique
      name      String
      createdAt DateTime @default(now())
      updatedAt DateTime @updatedAt
      posts     Post[]
    }
    
    model Post {
      id        String   @id @default(cuid())
      title     String
      content   String
      published Boolean  @default(false)
      author    User     @relation(fields: [authorId], references: [id])
      authorId  String
      createdAt DateTime @default(now())
      updatedAt DateTime @updatedAt
    }
    
    // lib/db.ts
    import { PrismaClient } from '@prisma/client';
    
    const globalForPrisma = globalThis as unknown as {
      prisma: PrismaClient | undefined;
    };
    
    export const prisma = globalForPrisma.prisma ?? new PrismaClient();
    
    if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma;
    
    // API routes with type safety
    import { z } from 'zod';
    
    const createPostSchema = z.object({
      title: z.string().min(1).max(200),
      content: z.string().min(1),
      authorId: z.string().cuid(),
    });
    
    export async function POST(request: Request) {
      try {
        const body = await request.json();
        const { title, content, authorId } = createPostSchema.parse(body);
        
        const post = await prisma.post.create({
          data: {
            title,
            content,
            authorId,
          },
          include: {
            author: true,
          },
        });
        
        return Response.json(post, { status: 201 });
      } catch (error) {
        if (error instanceof z.ZodError) {
          return Response.json(
            { errors: error.flatten().fieldErrors },
            { status: 400 }
          );
        }
        
        return Response.json(
          { error: 'Internal server error' },
          { status: 500 }
        );
      }
    }
    

    State Management with Zustand

    // store/userStore.ts
    import { create } from 'zustand';
    import { devtools, persist } from 'zustand/middleware';
    
    interface User {
      id: string;
      name: string;
      email: string;
    }
    
    interface UserStore {
      user: User | null;
      isLoading: boolean;
      login: (email: string, password: string) => Promise<void>;
      logout: () => void;
      updateProfile: (updates: Partial<User>) => void;
    }
    
    export const useUserStore = create<UserStore>()(
      devtools(
        persist(
          (set, get) => ({
            user: null,
            isLoading: false,
            
            login: async (email: string, password: string) => {
              set({ isLoading: true });
              try {
                const response = await fetch('/api/auth/login', {
                  method: 'POST',
                  headers: { 'Content-Type': 'application/json' },
                  body: JSON.stringify({ email, password }),
                });
                
                if (response.ok) {
                  const user = await response.json();
                  set({ user, isLoading: false });
                } else {
                  throw new Error('Login failed');
                }
              } catch (error) {
                set({ isLoading: false });
                throw error;
              }
            },
            
            logout: () => {
              set({ user: null });
            },
            
            updateProfile: (updates) => {
              const currentUser = get().user;
              if (currentUser) {
                set({ user: { ...currentUser, ...updates } });
              }
            },
          }),
          {
            name: 'user-storage',
            partialize: (state) => ({ user: state.user }),
          }
        )
      )
    );
    
    // Usage in components
    function ProfilePage() {
      const { user, isLoading, updateProfile } = useUserStore();
    
      if (isLoading) return <div>Loading...</div>;
      if (!user) return <div>Please log in</div>;
    
      return (
        <div>
          <h1>Profile</h1>
          <p>Name: {user.name}</p>
          <p>Email: {user.email}</p>
          <button 
            onClick={() => updateProfile({ name: 'Updated Name' })}
          >
            Update Name
          </button>
        </div>
      );
    }
    

    Modern Development Workflow

    Configuration Files

    // package.json
    {
      "name": "my-typescript-app",
      "version": "0.1.0",
      "type": "module",
      "scripts": {
        "dev": "next dev --turbopack",
        "build": "next build",
        "start": "next start",
        "lint": "eslint . --max-warnings 0",
        "lint:fix": "eslint . --fix",
        "type-check": "tsc --noEmit",
        "test": "vitest",
        "test:ui": "vitest --ui",
        "test:e2e": "playwright test",
        "test:e2e:ui": "playwright test --ui"
      },
      "dependencies": {
        "next": "^15.0.0",
        "react": "^19.0.0",
        "react-dom": "^19.0.0",
        "@trpc/client": "^11.0.0",
        "@trpc/server": "^11.0.0",
        "@trpc/react-query": "^11.0.0",
        "zod": "^3.23.0",
        "zustand": "^5.0.0"
      },
      "devDependencies": {
        "@types/node": "^22.0.0",
        "@types/react": "^19.0.0",
        "@types/react-dom": "^19.0.0",
        "typescript": "^5.6.0",
        "eslint": "^9.0.0",
        "prettier": "^3.3.0",
        "vitest": "^2.0.0",
        "@testing-library/react": "^16.0.0",
        "playwright": "^1.48.0"
      }
    }
    
    // tsconfig.json
    {
      "compilerOptions": {
        "target": "ES2022",
        "lib": ["dom", "dom.iterable", "ES2022"],
        "allowJs": true,
        "skipLibCheck": true,
        "strict": true,
        "forceConsistentCasingInFileNames": true,
        "noEmit": true,
        "esModuleInterop": true,
        "module": "ESNext",
        "moduleResolution": "bundler",
        "resolveJsonModule": true,
        "isolatedModules": true,
        "jsx": "preserve",
        "incremental": true,
        "plugins": [
          {
            "name": "next"
          }
        ],
        "baseUrl": ".",
        "paths": {
          "@/*": ["./src/*"],
          "@/components/*": ["./src/components/*"],
          "@/lib/*": ["./src/lib/*"],
          "@/types/*": ["./src/types/*"]
        }
      },
      "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
      "exclude": ["node_modules"]
    }
    
    // eslint.config.js (ESLint Flat Config)
    import js from '@eslint/js';
    import typescript from '@typescript-eslint/eslint-plugin';
    import typescriptParser from '@typescript-eslint/parser';
    import react from 'eslint-plugin-react';
    import reactHooks from 'eslint-plugin-react-hooks';
    
    export default [
      js.configs.recommended,
      {
        files: ['**/*.{ts,tsx}'],
        languageOptions: {
          parser: typescriptParser,
          parserOptions: {
            ecmaVersion: 'latest',
            sourceType: 'module',
            ecmaFeatures: {
              jsx: true,
            },
          },
        },
        plugins: {
          '@typescript-eslint': typescript,
          'react': react,
          'react-hooks': reactHooks,
        },
        rules: {
          ...typescript.configs.recommended.rules,
          '@typescript-eslint/no-unused-vars': 'error',
          '@typescript-eslint/no-explicit-any': 'warn',
          'react/react-in-jsx-scope': 'off',
          'react-hooks/rules-of-hooks': 'error',
          'react-hooks/exhaustive-deps': 'warn',
        },
        settings: {
          react: {
            version: 'detect',
          },
        },
      },
    ];
    

    CI/CD Pipeline

    # .github/workflows/ci.yml
    name: CI
    
    on:
      push:
        branches: [main, develop]
      pull_request:
        branches: [main, develop]
    
    jobs:
      test:
        runs-on: ubuntu-latest
        
        strategy:
          matrix:
            node-version: [20.x, 22.x]
        
        steps:
          - uses: actions/checkout@v4
          
          - name: Setup Node.js ${{ matrix.node-version }}
            uses: actions/setup-node@v4
            with:
              node-version: ${{ matrix.node-version }}
              cache: 'pnpm'
          
          - name: Install pnpm
            uses: pnpm/action-setup@v3
            with:
              version: 9
          
          - name: Install dependencies
            run: pnpm install --frozen-lockfile
          
          - name: Type check
            run: pnpm type-check
          
          - name: Lint
            run: pnpm lint
          
          - name: Test
            run: pnpm test
          
          - name: E2E tests
            run: pnpm test:e2e
          
          - name: Build
            run: pnpm build
          
          - name: Upload coverage
            uses: codecov/codecov-action@v4
            with:
              file: ./coverage/lcov.info
    

    Created by: MoAI Language Skill Factory
    Last Updated: 2025-11-06
    Version: 2.0.0
    TypeScript Target: 5.6+ with latest language features

    This skill provides comprehensive TypeScript development guidance with 2025 best practices, covering everything from basic type safety to advanced full-stack patterns and enterprise-grade applications.

    Recommended Servers
    GroundRoute: Web Search for AI Agents across 6 Engines ($10 free credit)
    GroundRoute: Web Search for AI Agents across 6 Engines ($10 free credit)
    OpenZeppelin
    OpenZeppelin
    Context7
    Context7
    Repository
    kivo360/quickhooks
    Files