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:
- Increment session counter —
data.wrongTimestracks mistakes in the current practice run - Add to global store —
store.wrong.wordsmaintains the canonical list of all wrong words - Add to session list —
data.wrongWordspowers 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
- Marking wrong:
usePracticeWordSession.tsdetects mismatches and populates bothstore.wrong.words(global) anddata.wrongWords(session) - Global access: Use
useBaseStore().wrong.wordsfromapp/core/stores/base.ts - Session access: Use
usePracticeWordNavigator().getSource('wrongWords')fromapp/core/composables/practice-words/usePracticeWordNavigator.ts - Deduplication: Both lists prevent duplicate entries via
findIndexandsomechecks - Cleanup: The
wrongWordClearaction filters completed words fromdata.wrongWords
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →