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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions