Skip to content

TS compilation issue #52

@AJReade

Description

@AJReade

TypeScript Compiler Crash with moduleResolution: "bundler"

Summary

The live_toast dependency causes a TypeScript compiler crash when imported in projects using moduleResolution: "bundler". The crash occurs with an internal TypeScript error: "Debug Failure. False expression" in the getConstructorDefinedThisAssignmentTypes function.

Environment

  • TypeScript Version: 5.4.5 (also tested with 5.8.3)
  • Node.js Version: v22.12.0
  • Operating System: macOS 24.5.0
  • live_toast Version: [version from deps/live_toast]

TypeScript Configuration

{
  "compilerOptions": {
    "target": "ES2020",
    "lib": ["dom", "dom.iterable", "ES2020"],
    "allowJs": true,
    "skipLibCheck": true,
    "types": ["vite/client"],
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "esnext",
    "moduleResolution": "bundler",
    "isolatedModules": true,
    "resolveJsonModule": true,
    "noEmit": true,
    "jsx": "react"
  }
}

Reproduction Steps

  1. Create a TypeScript project with moduleResolution: "bundler"
  2. Import createLiveToastHook from live_toast:
    import { createLiveToastHook } from "../../deps/live_toast";
  3. Run TypeScript compilation: npx tsc

Expected Behavior

TypeScript compilation should complete successfully.

Actual Behavior

TypeScript compiler crashes with the following error:

Error: Debug Failure. False expression.
    at getConstructorDefinedThisAssignmentTypes (/path/to/node_modules/typescript/lib/tsc.js:52803:11)
    at getWidenedTypeForAssignmentDeclaration (/path/to/node_modules/typescript/lib/tsc.js:52614:78)
    at getTypeOfVariableOrParameterOrPropertyWorker (/path/to/node_modules/typescript/lib/tsc.js:53029:14)
    at getTypeOfVariableOrParameterOrProperty (/path/to/node_modules/typescript/lib/tsc.js:52974:20)
    at getTypeOfSymbol (/path/to/node_modules/typescript/lib/tsc.js:53306:14)
    at getWriteTypeOfSymbol (/path/to/node_modules/typescript/lib/tsc.js:53284:29)
    at checkPropertyAccessExpressionOrQualifiedName (/path/to/node_modules/typescript/lib/tsc.js:70818:116)
    at checkPropertyAccessExpression (/path/to/node_modules/typescript/lib/tsc.js:70576:94)
    at checkExpressionWorker (/path/to/node_modules/typescript/lib/tsc.js:76295:16)
    at checkExpression (/path/to/node_modules/typescript/lib/tsc.js:76216:32)

Root Cause Analysis

The issue appears to be caused by the global interface extension in live_toast.ts:

declare global {
  interface HTMLElement {
    order: number
    targetDestination: string
  }
}

When TypeScript uses moduleResolution: "bundler", it encounters a bug in its type inference system when processing property access chains on these extended global interfaces, particularly in the context of constructor-defined property assignments.

Workarounds Attempted

  1. Skipping TypeScript compilation - Works but loses type checking benefits
  2. Using @ts-ignore - Doesn't prevent the crash
  3. Excluding files with exclude - Still processes imports
  4. Creating wrapper files - Still triggers the crash
  5. Custom type declarations - Doesn't resolve the internal compiler bug

Working Workaround

Currently, the only viable workaround is to skip TypeScript type checking in the build process:

{
  "scripts": {
    "build": "vite build"  // instead of "tsc && vite build"
  }
}

Suggested Fixes

  1. Modify the global interface extension to use optional properties:

    declare global {
      interface HTMLElement {
        order?: number;
        targetDestination?: string;
      }
    }
  2. Use a more specific interface instead of extending the global HTMLElement:

    interface LiveToastElement extends HTMLElement {
      order: number;
      targetDestination: string;
    }
  3. Add a TypeScript configuration note in the documentation about moduleResolution compatibility

Additional Context

  • The crash occurs specifically with moduleResolution: "bundler"
  • Works fine with moduleResolution: "node"
  • The issue is reproducible across different TypeScript versions (5.4.5 and 5.8.3)
  • This affects Phoenix LiveView projects using modern TypeScript configurations

Impact

This issue prevents developers from using modern TypeScript configurations (moduleResolution: "bundler") with live_toast, forcing them to either:

  • Use older module resolution strategies
  • Skip type checking entirely
  • Avoid using live_toast

Would appreciate any guidance on resolving this TypeScript compatibility issue!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions