How to Mark a Word as Wrong and Retrieve the Wrong Words List in TypeWords

In TypeWords, a word is marked as wrong during a practice session when the user's input doesn't match the expected word, and the wrong words list can be retrieved from either store.wrong.words (global store) or data.wrongWords (session data).

TypeWords is an open-source typing practice application that tracks your mistakes to help you improve. Understanding how the application records and manages wrong words is essential for customizing practice sessions, building statistics dashboards, or implementing retry flows. This guide explains the complete wrong-word lifecycle based on the TypeWords source code.

How Words Are Marked as Wrong

The wrong-word detection logic lives in app/core/composables/practice-words/usePracticeWordSession.ts. When a typing mismatch occurs, the system executes a three-step process:

  1. Increment session counter — data.wrongTimes tracks mistakes in the current practice run
  2. Add to global store — store.wrong.words maintains the canonical list of all wrong words
  3. Add to session list — data.wrongWords powers the retry-specific flow

Here's the core implementation from lines 167-188:

// Inside usePracticeWordSession.ts – wrong-word detection
if (isWrong) {
  // 1. Increment per-session wrong counter
  data.wrongTimes++

  // 2. Add to global wrong-word store (deduplicated)
  const storedWrongIndex = store.wrong.words.findIndex(item => item.word === word.word)
  if (storedWrongIndex < 0) {
    store.wrong.words.push(word)
    store.wrong.length = store.wrong.words.length
  }

  // 3. Add to session-level wrong-words list (for retry flow)
  if (!data.wrongWords.some(item => item.word === word.word)) {
    data.wrongWords.push(word)
  }
}

The global store (store.wrong.words) persists across the entire application session and provides the length property for quick statistics display. The session data (data.wrongWords) is scoped to the current practice flow and drives the "Wrong Words Retry" feature.

Where Wrong Words Are Stored

TypeWords maintains wrong words in two complementary locations:

Location File Purpose
store.wrong.words app/core/stores/base.ts (line 112) Global collection for statistics and persistence
data.wrongWords app/core/composables/practice-words/usePracticeWordSession.ts (lines 175-188) Session-specific list for retry workflows

Global Store Structure

The base store in app/core/stores/base.ts defines the wrong-words structure:

// From app/core/stores/base.ts
interface WrongState {
  words: Word[]      // All wrong words in current session
  length: number     // Cached length for UI performance
}

The length property stays synchronized whenever words are added or removed, avoiding expensive array length calculations in reactive components.

Session Data Interface

The PracticeData type in app/core/types/types.ts declares the session-level list:

// From app/core/types/types.ts
interface PracticeData {
  wrongWords: Word[]      // Wrong words for current retry cycle
  wrongTimes: number      // Total mistake count this session
  // ... other practice fields
}

Retrieving the Wrong Words List

Method 1: Access Global Store Directly

For statistics panels, progress tracking, or cross-session analysis:

import { useBaseStore } from '@/core/stores/base'

const store = useBaseStore()

// Get all wrong words
const allWrongWords = store.wrong.words

// Get count (cached for performance)
const wrongCount = store.wrong.length

// Map to displayable strings
const wrongWordStrings = allWrongWords.map(w => w.word)

Source: app/core/stores/base.ts — the store exposes wrong.words and wrong.length as reactive state.

Method 2: Access via Practice Navigator

For retry flows and practice-specific logic, use usePracticeWordNavigator:

import { usePracticeWordNavigator } from '@/core/composables/practice-words/usePracticeWordNavigator'

const navigator = usePracticeWordNavigator()

// Retrieve words specifically for retry
const wrongWordsForRetry = navigator.getSource('wrongWords')

The navigator's getSource method (line 54 in usePracticeWordNavigator.ts) returns data.wrongWords when the source parameter is 'wrongWords':

// From usePracticeWordNavigator.ts — line 54
case 'wrongWords':
  return data.wrongWords

This abstraction allows the UI to switch between word sources (regular practice, wrong-word retry, favorites, etc.) without knowing implementation details.

Clearing and Managing Wrong Words

When users complete a retry cycle or manually clear their mistakes, TypeWords filters the list using checkWordIsNeedNext:

// From usePracticeWordNavigator.ts — lines 337-340
data.wrongWords = data.wrongWords.filter(v => !deps.checkWordIsNeedNext(v))

if (data.wrongWords.length > 0) {
  // Continue retrying remaining words
}

This cleanup happens in the wrongWordClear action handler. Words that pass the check (no longer need practice) are removed from both the session list and, indirectly, from the global store through reactive synchronization.

Persisting Wrong Words

The cache utility in app/core/utils/cache.ts handles serialization of practice data, including wrongWordsStr — a stringified version of the wrong words array for localStorage persistence. This enables wrong-word tracking to survive page refreshes during a single browser session.

Summary

Frequently Asked Questions

How does TypeWords prevent the same word from being added twice to the wrong words list?

Both storage locations check for existing entries before pushing. The global store uses findIndex on store.wrong.words, while the session list uses some on data.wrongWords. These checks run on every wrong-word detection event in usePracticeWordSession.ts (lines 172-176 and 177-180).

What's the difference between store.wrong.words and data.wrongWords?

store.wrong.words lives in the global Pinia store and persists for the entire application lifecycle — it powers statistics and cross-session tracking. data.wrongWords is local to the current practice session composable and specifically drives the wrong-word retry workflow. The session list can be filtered and cleared independently without affecting historical statistics.

Can I access wrong words from outside the practice composables?

Yes. Import useBaseStore from @/core/stores/base anywhere in the application to access store.wrong.words. This store is framework-agnostic and doesn't require being inside a practice session context, making it suitable for dashboard components, statistics widgets, or export features.

When are wrong words removed from the lists?

Words are filtered from data.wrongWords during the wrongWordClear action in usePracticeWordNavigator.ts (lines 337-340) when they no longer need practice — typically after successful completion or manual dismissal. The global store.wrong.words maintains a broader historical record that may persist longer depending on the application's session management.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →