Bird
Raised Fist0
Vueframework~10 mins

Typing composables in Vue - Step-by-Step Execution

Choose your learning style10 modes available
Concept Flow - Typing composables
Define composable function
↓
Add TypeScript types to inputs/outputs
↓
Use ref/reactive with typed values
↓
Return typed state and methods
↓
Consume composable with type safety
This flow shows how to create a Vue composable with TypeScript types to ensure inputs and outputs are correctly typed and safe to use.
Execution Sample
Vue
import { ref } from 'vue'

function useCounter(initial: number) {
  const count = ref<number>(initial)
  function increment() { count.value++ }
  return { count, increment }
}
A simple typed composable that manages a counter with a typed initial value and typed state.
Execution Table
StepActionInput/StateOutput/State Change
1Call useCounter with initial=5initial=5count = ref(5) with type number
2Define increment functioncount=ref(5)increment() ready to increase count.value
3Return { count, increment }count=ref(5)Composable returns typed count and increment
4Call increment()count.value=5count.value becomes 6
5Access count.valuecount.value=6Output is 6
💡 Composable returns typed state and methods; usage updates count.value correctly.
Variable Tracker
VariableStartAfter 1After 2After 3After 4Final
count.valueundefined55566
Key Moments - 3 Insights
Why do we write ref<number>(initial) instead of just ref(initial)?
Typing ref<number> explicitly tells TypeScript the value inside is a number, ensuring type safety as shown in execution_table step 1.
What happens if increment() is called before count is initialized?
In this composable, count is initialized immediately, so increment() safely updates count.value as seen in step 4.
How does TypeScript help when using the returned composable?
TypeScript knows count is a Ref<number> and increment is a function, preventing mistakes when accessing or modifying them, as shown in step 5.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table, what is the value of count.value after step 4?
Aundefined
B6
C5
D7
💡 Hint
Check the 'Output/State Change' column at step 4 in execution_table.
At which step is the increment function defined and ready to use?
AStep 2
BStep 1
CStep 3
DStep 4
💡 Hint
Look at the 'Action' column describing function definition in execution_table.
If we change initial to a string, what will happen to the typing?
Aincrement function will convert string to number automatically
Bcount.value will accept string without error
CTypeScript will show an error because count expects a number
DNo change, code runs fine
💡 Hint
Refer to the typing in the composable definition and variable_tracker for count.value type.
Concept Snapshot
Typing composables in Vue:
- Define composable function with typed parameters
- Use ref<T> or reactive with explicit types
- Return typed state and methods
- TypeScript ensures safe usage and catches errors
- Helps maintain clear contracts for composables
Full Transcript
Typing composables in Vue means adding TypeScript types to the inputs and outputs of your composable functions. You start by defining a composable function that takes typed parameters. Inside, you use Vue's ref or reactive with explicit type annotations to hold state. You then return the typed state and any methods. This approach helps TypeScript understand what types your composable expects and returns, so it can catch mistakes early. For example, a useCounter composable takes a number initial value, creates a ref<number> count, and returns count and an increment function. When increment is called, count.value increases safely. If you try to pass a wrong type, TypeScript will warn you. This makes your composables safer and easier to use.

Practice

(1/5)
1. What is the main purpose of typing composables in Vue with TypeScript?
easy
A. To catch errors early and improve code understanding
B. To make the app run faster
C. To reduce the size of the final bundle
D. To avoid using reactive data

Solution

  1. Step 1: Understand typing benefits

    Typing helps catch mistakes before running the code and clarifies what data types are used.
  2. Step 2: Compare options

    Only To catch errors early and improve code understanding correctly states the purpose of typing composables; others are unrelated benefits.
  3. Final Answer:

    To catch errors early and improve code understanding -> Option A
  4. Quick Check:

    Typing composables = catch errors early [OK]
Hint: Typing helps find mistakes before running code [OK]
Common Mistakes:
  • Thinking typing improves app speed
  • Confusing typing with bundle size reduction
  • Believing typing removes reactive data
2. Which of the following is the correct way to type a reactive number in a Vue composable using TypeScript?
easy
A. const count: Ref<number> = ref(0);
B. const count: reactive<number> = reactive(0);
C. const count: number = ref(0);
D. const count: Ref = ref('0');

Solution

  1. Step 1: Identify correct typing for reactive refs

    Vue uses Ref<Type> to type reactive refs, so Ref<number> is correct for a number.
  2. Step 2: Check each option

    const count: Ref<number> = ref(0); correctly types count as Ref<number>. const count: reactive<number> = reactive(0); uses wrong syntax, C assigns ref to number type, D uses wrong type and string value.
  3. Final Answer:

    const count: Ref<number> = ref(0); -> Option A
  4. Quick Check:

    Use Ref<Type> for reactive refs [OK]
Hint: Use Ref<Type> to type reactive refs in composables [OK]
Common Mistakes:
  • Using reactive instead of Ref for refs
  • Assigning ref() to plain types
  • Mismatching value type and Ref generic
3. Given this composable code, what is the type of message inside the component?
import { ref } from 'vue';

export function useMessage() {
  const message = ref('Hello');
  return { message };
}
medium
A. string
B. Ref<string>
C. Ref<any>
D. any

Solution

  1. Step 1: Understand ref return type

    The ref function returns a Ref object wrapping the value type, here a string.
  2. Step 2: Determine message type

    Since message is created by ref('Hello'), its type is Ref<string>.
  3. Final Answer:

    Ref<string> -> Option B
  4. Quick Check:

    ref('text') returns Ref<string> [OK]
Hint: ref('text') returns Ref<string> type [OK]
Common Mistakes:
  • Assuming message is plain string
  • Using Ref<any> without specifying type
  • Confusing Ref<string> with string
4. Identify the error in this typed composable code:
import { ref, Ref } from 'vue';

export function useCounter(): { count: Ref<number> } {
  const count = ref('0');
  return { count };
}
medium
A. Ref type is not imported
B. Return type is missing
C. count should be reactive, not ref
D. ref is called with a string instead of a number

Solution

  1. Step 1: Check ref argument type

    The function expects count to be Ref<number>, but ref is called with a string '0'.
  2. Step 2: Identify mismatch error

    This causes a type mismatch error because the initial value type does not match the declared Ref generic.
  3. Final Answer:

    ref is called with a string instead of a number -> Option D
  4. Quick Check:

    ref argument type must match Ref generic [OK]
Hint: Check ref initial value matches declared Ref type [OK]
Common Mistakes:
  • Passing wrong type to ref()
  • Ignoring return type mismatch
  • Confusing reactive and ref usage
5. How would you correctly type a composable that returns a reactive object with a string title and a number count using Vue's Ref type?
import { ref, Ref } from 'vue';

export function useData() {
  const title = ref('My Title');
  const count = ref(10);
  return { title, count };
}
hard
A. export function useData(): { title: reactive<string>; count: reactive<number> }
B. export function useData(): { title: string; count: number }
C. export function useData(): { title: Ref<string>; count: Ref<number> }
D. export function useData(): { title: Ref<any>; count: Ref<any> }

Solution

  1. Step 1: Identify types of returned refs

    Both title and count are refs holding string and number respectively, so their types are Ref<string> and Ref<number>.
  2. Step 2: Match return type signature

    The function return type should reflect these as an object with keys typed as Ref<string> and Ref<number>.
  3. Final Answer:

    export function useData(): { title: Ref<string>; count: Ref<number> } -> Option C
  4. Quick Check:

    Return type matches Ref types of reactive data [OK]
Hint: Return type must match Ref types of reactive variables [OK]
Common Mistakes:
  • Typing return values as plain string or number
  • Using Ref<any> instead of specific types
  • Using reactive instead of Ref in type
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