We use cookies to enhance your experience on the site
CodeWorlds

Typing ref, reactive, and computed

In the space station systems, every value has its precise type. Vue 3 Composition API has excellent TypeScript support —

ref
,
reactive
, and
computed
can be fully typed.

Typing ref

ref
accepts a generic type
Ref<T>
:

1<script setup lang="ts">
2import { ref, type Ref } from 'vue'
3
4// Type inference
5const count = ref(0)           // Ref<number>
6const name = ref('NOVA LAB')   // Ref<string>
7
8// Explicit typing
9const status = ref<string>('active')
10const data = ref<number[]>([1, 2, 3])
11
12// Union type — useful when the value can be null
13const selectedId = ref<string | null>(null)
14
15// Explicit Ref type
16const temperature: Ref<number> = ref(-63)
17</script>

Typing reactive

reactive
automatically infers types from the object:

1<script setup lang="ts">
2import { reactive } from 'vue'
3
4interface StationState {
5  name: string
6  power: number
7  modules: string[]
8  coordinates: { x: number; y: number; z: number }
9}
10
11const station = reactive<StationState>({
12  name: 'NOVA LAB',
13  power: 100,
14  modules: ['Lab', 'Bridge', 'Hangar'],
15  coordinates: { x: 0, y: 0, z: 0 }
16})
17
18// TypeScript knows the exact structure
19station.power = 95         // OK
20// station.power = 'high'  // ERROR! number expected
21// station.unknown = true  // ERROR! Unknown property
22</script>

Typing computed

computed
automatically infers the return type:

1<script setup lang="ts">
2import { ref, computed } from 'vue'
3
4const power = ref(85)
5const maxPower = ref(100)
6
7// Inferred type: ComputedRef<number>
8const powerPercentage = computed(() => {
9  return (power.value / maxPower.value) * 100
10})
11
12// Inferred type: ComputedRef<string>
13const powerStatus = computed(() => {
14  if (power.value > 80) return 'optimal'
15  if (power.value > 40) return 'moderate'
16  return 'critical'
17})
18
19// Explicit typing
20const label = computed<string>(() => {
21  return 'Power: ' + powerPercentage.value.toFixed(1) + '%'
22})
23</script>

Writable computed with Types

1<script setup lang="ts">
2import { ref, computed } from 'vue'
3
4const celsius = ref(20)
5
6const fahrenheit = computed<number>({
7  get: () => celsius.value * 9/5 + 32,
8  set: (val: number) => {
9    celsius.value = (val - 32) * 5/9
10  }
11})
12
13fahrenheit.value = 68  // celsius becomes 20
14</script>

Typing Reactive Arrays

1<script setup lang="ts">
2import { ref } from 'vue'
3
4interface LogEntry {
5  id: number
6  message: string
7  level: 'info' | 'warn' | 'error'
8  timestamp: Date
9}
10
11const logs = ref<LogEntry[]>([])
12
13function addLog(message: string, level: LogEntry['level']) {
14  logs.value.push({
15    id: Date.now(),
16    message,
17    level,
18    timestamp: new Date()
19  })
20}
21
22// TypeScript checks argument correctness
23addLog('System started', 'info')     // OK
24// addLog('Error', 'critical')       // ERROR! 'critical' is not valid
25</script>
Go to CodeWorlds