Skip to content

Add TypeScript strict mode compliance #10

@koistya

Description

@koistya

Description

Enable TypeScript strict mode in tsconfig.json and fix all resulting type issues. The codebase currently has several @ts-ignore comments and may have implicit any types that should be properly typed.

What needs to be done

  1. Enable strict mode in tsconfig.json:

    {
      "compilerOptions": {
        "strict": true,
        // This enables:
        // "noImplicitAny": true,
        // "strictNullChecks": true,
        // "strictFunctionTypes": true,
        // "strictBindCallApply": true,
        // "strictPropertyInitialization": true,
        // "noImplicitThis": true,
        // "alwaysStrict": true
      }
    }
  2. Fix all type errors that arise

  3. Remove @ts-ignore comments where possible

  4. Add proper types for runtime-specific globals (Bun, Deno)

Why this matters

TypeScript strict mode catches many bugs at compile time:

  • Null/undefined access errors
  • Incorrect function signatures
  • Missing error handling
  • Type mismatches

Current @ts-ignore usage hides potential issues:

  • Line 132, 284, 597, 602 in src/server.ts - Runtime global detection

Implementation considerations

⚠️ Note: This feature requires critical thinking during implementation. Consider:

  1. Runtime types: Instead of @ts-ignore for Bun/Deno globals, should we create proper type definitions or use type guards?

  2. Breaking changes: Strict mode might reveal API issues. Should we fix them (breaking change) or maintain compatibility?

  3. Alternative approach: Enable strict flags one at a time to make the migration manageable

  4. Type assertions vs type guards: When fixing errors, prefer type guards over assertions for runtime safety

  5. Any migration: Instead of jumping to strict types, should we first migrate from any to unknown?

Current problem areas

// src/server.ts:132
// @ts-ignore - Bun global not available in TypeScript definitions
this.server = Bun.serve({
  port,
  hostname,
  fetch: (request: Request) => this.handleRequest(request),
});

Suggested solutions

Option 1: Ambient declarations

// src/types/runtime.d.ts
declare global {
  const Bun: {
    serve(options: {
      port: number;
      hostname: string;
      fetch: (request: Request) => Response | Promise<Response>;
    }): {
      stop(): void;
      port: number;
    };
  } | undefined;
  
  const Deno: {
    serve(
      options: { port: number; hostname: string; signal?: AbortSignal },
      handler: (request: Request) => Response | Promise<Response>
    ): { finished: Promise<void> };
  } | undefined;
}

Option 2: Runtime detection with type guards

function isBunRuntime(): boolean {
  return typeof globalThis.Bun !== "undefined";
}

function isDenoRuntime(): boolean {
  return typeof globalThis.Deno !== "undefined";
}

if (isBunRuntime()) {
  // TypeScript knows Bun exists here
  const server = (globalThis as any).Bun.serve({...});
}

Option 3: Factory pattern

interface RuntimeServer {
  start(options: ServerOptions): Promise<void>;
  stop(): Promise<void>;
}

class BunServer implements RuntimeServer {
  // Bun-specific implementation
}

class DenoServer implements RuntimeServer {
  // Deno-specific implementation
}

class NodeServer implements RuntimeServer {
  // Node-specific implementation
}

function createServer(): RuntimeServer {
  if (typeof globalThis.Bun !== "undefined") {
    return new BunServer();
  }
  // ...
}

Migration strategy

  1. Create type definitions for runtime globals
  2. Enable noImplicitAny first
  3. Fix implicit any types
  4. Enable strictNullChecks
  5. Fix null/undefined issues
  6. Enable remaining strict flags
  7. Remove all @ts-ignore comments

Expected type issues to fix

  • Implicit any in error handlers
  • Possible null/undefined access
  • Missing return types
  • Untyped function parameters
  • Type assertions that could be type guards

Skills required

  • TypeScript (advanced)
  • Type system understanding
  • Runtime environment differences
  • Refactoring skills

Difficulty

Easy to Medium - Depends on how many type issues exist

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions