Bird
Raised Fist0
Vueframework~20 mins

Type-safe stores with Pinia in Vue - Practice Problems & Coding Challenges

Choose your learning style10 modes available
Challenge - 5 Problems
🎖️
Pinia Type Safety Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ component_behavior
intermediate
2:00remaining
What is the output of this Pinia store state access?
Given the following Pinia store, what will be logged when console.log(store.user.name) runs?
Vue
import { defineStore } from 'pinia'

export const useUserStore = defineStore('user', {
  state: () => ({
    user: {
      name: 'Alice',
      age: 30
    }
  })
})

const store = useUserStore()
console.log(store.user.name)
ATypeError: Cannot read property 'name' of undefined
B"user"
Cundefined
D"Alice"
Attempts:
2 left
💡 Hint
Look at how the state is defined and accessed through the store instance.
📝 Syntax
intermediate
2:00remaining
Which option correctly defines a type-safe Pinia store state?
Choose the option that correctly defines a Pinia store with TypeScript types for state.
Vue
import { defineStore } from 'pinia'

interface Todo {
  id: number
  title: string
  done: boolean
}

export const useTodoStore = defineStore('todo', {
  state: () => ({
    todos: [] as Todo[]
  })
})
Astate: () => ({ todos: [] as Todo[] })
Bstate: () => ({ todos: [] }) as Todo[]
Cstate: () => <Todo[]>[]
Dstate: (): Todo[] => []
Attempts:
2 left
💡 Hint
Check how the array is typed inside the state function.
🔧 Debug
advanced
2:00remaining
Why does this Pinia store cause a runtime error?
Identify the cause of the runtime error in this Pinia store code.
Vue
import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', {
  state: () => ({
    count: 0
  }),
  actions: {
    increment() {
      this.count++
    }
  }
})

const store = useCounterStore()
store.increment()
console.log(store.count)
ASyntaxError: Unexpected token in actions
BTypeError: Cannot read property 'count' of undefined
CNo error; output is 1
DReferenceError: useCounterStore is not defined
Attempts:
2 left
💡 Hint
Check how actions access state properties using 'this'.
❓ state_output
advanced
2:00remaining
What is the value of store.fullName after calling store.setName('Bob', 'Smith')?
Consider this Pinia store with getters and actions. What will store.fullName be after calling store.setName('Bob', 'Smith')?
Vue
import { defineStore } from 'pinia'

export const useProfileStore = defineStore('profile', {
  state: () => ({
    firstName: '',
    lastName: ''
  }),
  getters: {
    fullName: (state) => `${state.firstName} ${state.lastName}`
  },
  actions: {
    setName(first, last) {
      this.firstName = first
      this.lastName = last
    }
  }
})

const store = useProfileStore()
store.setName('Bob', 'Smith')
A"Smith Bob"
B"Bob Smith"
C"Bob"
D""
Attempts:
2 left
💡 Hint
Look at how the getter combines state properties.
🧠 Conceptual
expert
3:00remaining
Which option best explains how Pinia ensures type safety in stores?
Select the explanation that correctly describes how Pinia achieves type safety when using TypeScript.
APinia uses TypeScript generics and infers types from the state, getters, and actions to provide full type safety and autocompletion.
BPinia requires manual type annotations on every property to enforce type safety, otherwise it defaults to any type.
CPinia disables type checking inside stores to improve performance and relies on runtime checks instead.
DPinia only supports type safety for state but not for getters or actions.
Attempts:
2 left
💡 Hint
Think about how TypeScript works with Pinia's store definitions.

Practice

(1/5)
1. What is the main benefit of using type-safe stores with Pinia in a Vue application?
easy
A. It speeds up the app by caching data on the server.
B. It automatically styles components based on state.
C. It replaces Vue Router for navigation.
D. It helps catch errors by checking data types during development.

Solution

  1. Step 1: Understand type safety in programming

    Type safety means the system checks that data matches expected types, reducing bugs.
  2. Step 2: Connect type safety to Pinia stores

    Pinia stores with types ensure state and actions use correct data types, catching mistakes early.
  3. Final Answer:

    It helps catch errors by checking data types during development. -> Option D
  4. Quick Check:

    Type safety = catches type errors [OK]
Hint: Type-safe means checking data types to avoid bugs [OK]
Common Mistakes:
  • Confusing type safety with styling or UI features
  • Thinking Pinia replaces routing
  • Assuming type safety improves runtime speed
2. Which of the following is the correct way to define a Pinia store with TypeScript for a state property count of type number?
easy
A. const useStore = defineStore('main', { state: () => ({ count: '0' }) })
B. const useStore = defineStore('main', { state: () => { count: 0 as number } })
C. const useStore = defineStore('main', { state: () => ({ count: 0 }) })
D. const useStore = defineStore('main', { state: () => ({ count: Number }) })

Solution

  1. Step 1: Check state initialization syntax

    State is a function returning an object with initial values; count should be a number, not string or type.
  2. Step 2: Identify correct type-safe initialization

    Using count: 0 correctly sets count as number; as number is unnecessary here.
  3. Final Answer:

    const useStore = defineStore('main', { state: () => ({ count: 0 }) }) -> Option C
  4. Quick Check:

    State count initialized as number = const useStore = defineStore('main', { state: () => ({ count: 0 }) }) [OK]
Hint: Initialize state with correct value type directly [OK]
Common Mistakes:
  • Using string '0' instead of number 0
  • Using type casts unnecessarily in state
  • Assigning type constructors like Number instead of values
3. Given this Pinia store using TypeScript:
const useCounterStore = defineStore('counter', {
  state: () => ({ count: 5 }),
  actions: {
    increment() { this.count++ }
  }
})

const store = useCounterStore()
store.increment()
console.log(store.count)

What will be logged to the console?
medium
A. 5
B. 6
C. undefined
D. Error: count is readonly

Solution

  1. Step 1: Understand initial state and action effect

    The state count starts at 5. The increment action increases it by 1.
  2. Step 2: Trace the code execution

    Calling store.increment() changes count from 5 to 6, then logging outputs 6.
  3. Final Answer:

    6 -> Option B
  4. Quick Check:

    5 + 1 = 6 [OK]
Hint: Increment adds 1 to count, so output is 6 [OK]
Common Mistakes:
  • Thinking state is immutable and causes error
  • Forgetting increment changes count
  • Assuming initial value remains unchanged
4. Identify the error in this Pinia store definition using TypeScript:
const useStore = defineStore('main', {
  state: () => ({ count: 0 }),
  actions: {
    increment() {
      this.count = this.count + 1
    },
    reset() {
      this.count = 'zero'
    }
  }
})
medium
A. Using string 'zero' to assign to number state property count causes a type error.
B. The increment method should use this.count++ instead of addition.
C. State must be an object, not a function returning an object.
D. The store name 'main' is invalid and must be uppercase.

Solution

  1. Step 1: Check state type and assignments

    The state count is a number initialized to 0.
  2. Step 2: Identify type mismatch in actions

    In reset(), assigning string 'zero' to count breaks type safety, causing error.
  3. Final Answer:

    Using string 'zero' to assign to number state property count causes a type error. -> Option A
  4. Quick Check:

    Assigning wrong type to state = Using string 'zero' to assign to number state property count causes a type error. [OK]
Hint: State types must match assigned values exactly [OK]
Common Mistakes:
  • Ignoring type mismatch errors
  • Thinking addition syntax is wrong
  • Believing state must be plain object, not function
  • Assuming store names must be uppercase
5. You want to create a type-safe Pinia store for a user profile with state properties name (string), age (number), and an action updateProfile that accepts a partial object to update state. Which approach correctly ensures type safety?
hard
A. Define an interface for state, use it in store, and type updateProfile parameter as Partial<State>.
B. Use any type for state and action parameters to allow flexibility.
C. Define state without types and cast inside updateProfile to avoid errors.
D. Use separate stores for each property to avoid typing complexity.

Solution

  1. Step 1: Define a TypeScript interface for the state

    Creating an interface with name: string and age: number sets clear expected types.
  2. Step 2: Use Partial<State> in updateProfile parameter

    This allows updating any subset of properties while keeping type safety.
  3. Step 3: Implement store using interface and typed action

    Using the interface in defineStore and typing updateProfile ensures safe updates.
  4. Final Answer:

    Define an interface for state, use it in store, and type updateProfile parameter as Partial<State>. -> Option A
  5. Quick Check:

    Interface + Partial parameter = Define an interface for state, use it in store, and type updateProfile parameter as Partial<State>. [OK]
Hint: Use interfaces and Partial type for safe partial updates [OK]
Common Mistakes:
  • Using any type loses type safety
  • Casting types inside actions hides errors
  • Splitting state unnecessarily complicates design
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard