Skip to main content

Overview

React Hotkeys Hook is written in TypeScript and provides complete type definitions out of the box. You don’t need to install any additional @types packages.

Import Types

All types are exported from the main package:
import { 
  useHotkeys, 
  type Options, 
  type Keys, 
  type HotkeyCallback,
  type HotkeysEvent 
} from 'react-hotkeys-hook'

Typed Hook Usage

Basic TypeScript Example

import { useHotkeys } from 'react-hotkeys-hook'
import { useState } from 'react'

function Counter() {
  const [count, setCount] = useState<number>(0)
  
  useHotkeys('ctrl+k', () => setCount(prev => prev + 1), [count])
  
  return <div>Count: {count}</div>
}

Typed Callback with Event Parameters

The callback receives strongly-typed parameters:
import { useHotkeys, type HotkeyCallback } from 'react-hotkeys-hook'

const handleHotkey: HotkeyCallback = (event, hotkeysEvent) => {
  // event is KeyboardEvent
  console.log('Key pressed:', event.key)
  console.log('Ctrl pressed:', event.ctrlKey)
  
  // hotkeysEvent is HotkeysEvent with metadata
  console.log('Hotkey triggered:', hotkeysEvent.hotkey)
  console.log('Keys:', hotkeysEvent.keys)
  console.log('Modifiers:', hotkeysEvent.ctrl, hotkeysEvent.shift)
}

useHotkeys('ctrl+s', handleHotkey)

Typed Refs for Focus Trapping

When using focus trapping, specify the element type as a generic parameter:
import { useHotkeys } from 'react-hotkeys-hook'

function FocusedInput() {
  // Specify HTMLInputElement for an input
  const inputRef = useHotkeys<HTMLInputElement>(
    'ctrl+s',
    () => console.log('Save from input')
  )
  
  return <input ref={inputRef} />
}

function FocusedDiv() {
  // Specify HTMLDivElement for a div
  const divRef = useHotkeys<HTMLDivElement>(
    'escape',
    () => console.log('Close')
  )
  
  return <div ref={divRef} tabIndex={-1}>Focusable div</div>
}

Generic Types for Different Elements

import { useHotkeys } from 'react-hotkeys-hook'

// Button
const buttonRef = useHotkeys<HTMLButtonElement>('enter', handleSubmit)

// Textarea
const textareaRef = useHotkeys<HTMLTextAreaElement>('ctrl+enter', handleSave)

// Any div or span
const containerRef = useHotkeys<HTMLDivElement>('escape', handleClose)

// Section or article
const sectionRef = useHotkeys<HTMLElement>('n', handleNext)

Typed Options

The Options type provides full IntelliSense for all configuration options:
import { useHotkeys, type Options } from 'react-hotkeys-hook'

const options: Options = {
  enabled: true,
  preventDefault: true,
  enableOnFormTags: ['input', 'textarea'],
  description: 'Save the current document',
  scopes: ['editor'],
  keydown: true,
  keyup: false,
}

useHotkeys('ctrl+s', handleSave, options)

Type-Safe Form Tags

The FormTags type ensures you only use valid tag names:
import { useHotkeys, type FormTags, type Options } from 'react-hotkeys-hook'

// Valid form tags
const validTags: readonly FormTags[] = [
  'input',
  'textarea',
  'select',
  'searchbox', // ARIA role
  'textbox',   // ARIA role
]

const options: Options = {
  enableOnFormTags: validTags,
}

useHotkeys('ctrl+k', handleCommand, options)

Conditional Trigger Functions

The Trigger type allows boolean or function:
import { useHotkeys, type Trigger, type Options } from 'react-hotkeys-hook'

// As a function
const enabledWhen: Trigger = (keyboardEvent, hotkeysEvent) => {
  // Only enable if not in an input field
  const target = keyboardEvent.target as HTMLElement
  return target.tagName !== 'INPUT'
}

const preventDefaultWhen: Trigger = (keyboardEvent) => {
  // Only prevent default for certain keys
  return keyboardEvent.key === 's'
}

const options: Options = {
  enabled: enabledWhen,
  preventDefault: preventDefaultWhen,
}

useHotkeys('ctrl+s', handleSave, options)

Working with Scopes

import { useHotkeysContext, type Scopes } from 'react-hotkeys-hook'

function ScopeManager() {
  const { enableScope, disableScope, activeScopes } = useHotkeysContext()
  
  // activeScopes is string[]
  const currentScopes: string[] = activeScopes
  
  // Scopes can be string or readonly string[]
  const editorScopes: Scopes = ['editor', 'textEdit']
  
  return (
    <div>
      <p>Active: {currentScopes.join(', ')}</p>
      <button onClick={() => enableScope('editor')}>
        Enable Editor
      </button>
    </div>
  )
}

Keys Type

The Keys type accepts string or array:
import { useHotkeys, type Keys } from 'react-hotkeys-hook'

// Single key
const singleKey: Keys = 'ctrl+s'
useHotkeys(singleKey, handleSave)

// Multiple keys
const multipleKeys: Keys = ['ctrl+s', 'cmd+s']
useHotkeys(multipleKeys, handleSave)

// Readonly array
const readonlyKeys: readonly string[] = ['a', 'b', 'c'] as const
useHotkeys(readonlyKeys, handleKey)

Custom Metadata

You can add custom metadata with type safety:
import { useHotkeys, type Options } from 'react-hotkeys-hook'

interface CustomMetadata {
  action: string
  category: string
  icon?: string
}

const options: Options = {
  description: 'Open command palette',
  metadata: {
    action: 'openCommandPalette',
    category: 'navigation',
    icon: 'command',
  } as CustomMetadata,
}

useHotkeys('ctrl+k', handleCommand, options)

Type Inference

TypeScript can often infer types automatically:
import { useHotkeys } from 'react-hotkeys-hook'

// Types are inferred
useHotkeys('ctrl+k', (event, hotkeysEvent) => {
  // event: KeyboardEvent (inferred)
  // hotkeysEvent: HotkeysEvent (inferred)
  console.log(event.key)
  console.log(hotkeysEvent.hotkey)
})

// Options are type-checked
useHotkeys('ctrl+s', handleSave, {
  enabled: true,              // ✓ boolean
  preventDefault: true,       // ✓ boolean or function
  enableOnFormTags: ['input'], // ✓ FormTags[]
  keydown: true,              // ✓ boolean
})

Common TypeScript Patterns

Extract Callback Type

import { useHotkeys, type HotkeyCallback } from 'react-hotkeys-hook'

const callbacks: Record<string, HotkeyCallback> = {
  save: (event) => console.log('Save'),
  copy: (event) => console.log('Copy'),
  paste: (event) => console.log('Paste'),
}

Object.entries(callbacks).forEach(([key, callback]) => {
  useHotkeys(`ctrl+${key[0]}`, callback)
})

Type-Safe Hotkey Registry

import { useHotkeys, type Options } from 'react-hotkeys-hook'

interface HotkeyConfig {
  keys: string
  description: string
  handler: () => void
  options?: Options
}

const hotkeys: HotkeyConfig[] = [
  {
    keys: 'ctrl+s',
    description: 'Save document',
    handler: () => console.log('Save'),
    options: { preventDefault: true },
  },
  {
    keys: 'ctrl+k',
    description: 'Open command palette',
    handler: () => console.log('Command palette'),
  },
]

function useHotkeyRegistry(hotkeys: HotkeyConfig[]) {
  hotkeys.forEach(({ keys, handler, options }) => {
    useHotkeys(keys, handler, options)
  })
}
All types are re-exported from the main package, so you always import from react-hotkeys-hook.
Use TypeScript’s IntelliSense to discover available options and type constraints as you type.

Build docs developers (and LLMs) love