Skip to content

TypeScript error: stopPropagation does not exist on KeyEvent type #7441

@CasualDeveloper

Description

@CasualDeveloper

Bug Description

The useKeyboard callback in dialog.tsx uses evt.stopPropagation(), but TypeScript reports:

TS2339: Property 'stopPropagation' does not exist on type 'KeyEvent'

Root Cause Analysis

The KeyEvent class in @opentui/core does have stopPropagation() properly typed:

// node_modules/@opentui/core/lib/KeyHandler.d.ts
export declare class KeyEvent implements ParsedKey {
  // ...
  preventDefault(): void;
  stopPropagation(): void;  // ✓ Exists
}

And @opentui/solid has properly typed exports in src/elements/hooks.d.ts:

export declare const useKeyboard: (callback: (key: KeyEvent) => void, options?: UseKeyboardOptions) => void;

However, the jsx-runtime.d.ts contains:

import type { DomNode } from "./dist"  // ← This pulls in dist/index.d.ts

And dist/index.d.ts has auto-generated loose types:

export function useKeyboard(callback: any, options: any): void;  // ← Types lost

When TypeScript resolves imports via the jsx-runtime (required for JSX components), it also loads dist/index.d.ts, which shadows the properly-typed exports with any types. But when using noImplicitAny or when the any type flows through, TypeScript can't infer that evt.stopPropagation() exists.

Impact

  • bun turbo typecheck fails
  • Pre-push hooks fail (blocking pushes without --no-verify)
  • Build still succeeds (Bun bundler doesn't type-check)

Reproduction

cd packages/opencode
bunx tsc --noEmit src/cli/cmd/tui/ui/dialog.tsx

Introduced In

Commit 1f9e195cd8ce6d9dcca4c966a7c9ba2f6222f29d ("stop esc propagation from dialogs")

Affected Code

// packages/opencode/src/cli/cmd/tui/ui/dialog.tsx:59-67
useKeyboard((evt) => {
  if (evt.name === "escape" && store.stack.length > 0) {
    const current = store.stack.at(-1)!
    current.onClose?.()
    setStore("stack", store.stack.slice(0, -1))
    evt.preventDefault()
    evt.stopPropagation()  // ← Error here
    refocus()
  }
})

Proposed Solutions

Option 1: Import KeyEvent type explicitly (recommended)

import { useKeyboard, useRenderer, useTerminalDimensions } from "@opentui/solid"
import type { KeyEvent } from "@opentui/core"  // Add explicit import

// Then either annotate the callback:
useKeyboard((evt: KeyEvent) => {
  // ...
})

Option 2: Type assertion (quick fix)

;(evt as any).stopPropagation()

Option 3: Upstream fix in @opentui/solid

Fix jsx-runtime.d.ts to import DomNode from the properly-typed source instead of dist:

- import type { DomNode } from "./dist"
+ import type { DomNode } from "./src/reconciler"

Environment

  • opencode version: v1.1.8+
  • @opentui/solid version: 0.1.70
  • @opentui/core version: 0.1.70

Metadata

Metadata

Assignees

Labels

opentuiThis relates to changes in v1.0, now that opencode uses opentui

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions