Kurs Vue.js · Moduł 15: TypeScript i Nuxt

Typowanie Props

2 min czytania
W tej lekcji5

W Laboratorium Kwantowym każdy moduł stacji musi precyzyjnie deklarować jakie dane przyjmuje. W Vue 3 z TypeScript używamy generycznej składni defineProps<{}>() do typowania propsow.

defineProps z generycznym typem

Zamiast runtime validation (obiekt z type, required), możemy użyć składni TypeScript:

1<script setup lang="ts">
2// Składnia generyczna - typy sprawdzane w czasie kompilacji
3const props = defineProps<{
4  title: string
5  count: number
6  isActive: boolean
7}>()
8</script>

To równoważne tradycyjnej składni:

1<script setup>
2// Stara składnia - runtime validation
3const props = defineProps({
4  title: { type: String, required: true },
5  count: { type: Number, required: true },
6  isActive: { type: Boolean, required: true }
7})
8</script>

Wyodrębnianie interfejsu

Gdy komponent ma wiele propsow, warto wyodrębnic interfejs:

1<script setup lang="ts">
2interface StationModuleProps {
3  name: string
4  status: 'online' | 'offline' | 'maintenance'
5  powerLevel: number
6  crew?: string[]  // opcjonalny prop (?)
7}
8
9const props = defineProps<StationModuleProps>()
10</script>

Znak ? oznacza, że prop jest opcjonalny - nie musi być przekazany.

withDefaults

TypeScript generics nie pozwalają na wartości domyślne w defineProps. Do tego służy withDefaults:

1<script setup lang="ts">
2interface PanelProps {
3  title: string
4  variant?: 'primary' | 'danger' | 'success'
5  maxItems?: number
6  showHeader?: boolean
7}
8
9const props = withDefaults(defineProps<PanelProps>(), {
10  variant: 'primary',
11  maxItems: 10,
12  showHeader: true
13})
14</script>

Teraz props.variant będzie 'primary' jeśli nie zostanie przekazany.

Union Types w Props

TypeScript pozwala definiować precyzyjne typy:

1<script setup lang="ts">
2type AlertLevel = 'info' | 'warning' | 'critical'
3
4interface AlertProps {
5  level: AlertLevel
6  message: string
7  code?: number
8}
9
10const props = defineProps<AlertProps>()
11</script>
12
13<template>
14  <div :class="['alert', props.level]">
15    {{ props.message }}
16  </div>
17</template>

Złożone typy Props

Props mogą zawierać zagnieżdżone obiekty i tablice:

1<script setup lang="ts">
2interface Coordinate {
3  x: number
4  y: number
5  z: number
6}
7
8interface SensorData {
9  id: string
10  location: Coordinate
11  readings: number[]
12  metadata?: Record<string, unknown>
13}
14
15interface SensorPanelProps {
16  sensors: SensorData[]
17  selectedId: string | null
18  onSelect?: (id: string) => void
19}
20
21const props = defineProps<SensorPanelProps>()
22</script>

Record<string, unknown> to typ słownikowy - obiekt z kluczami string i wartościami dowolnego typu.

Kod do tej lekcji: App.vue
1<script setup lang="ts">
2import { ref } from 'vue'
3import ModuleCard from './ModuleCard.vue'
4
5interface StationModule {
6  id: string
7  name: string
8  status: 'online' | 'offline' | 'maintenance'
9  power: number
10}
11
12const modules = ref<StationModule[]>([
13  { id: 'm1', name: 'Life Support', status: 'online', power: 95 },
14  { id: 'm2', name: 'Navigation', status: 'online', power: 88 },
15  { id: 'm3', name: 'Science Lab', status: 'maintenance', power: 40 },
16  { id: 'm4', name: 'Communications', status: 'offline', power: 0 }
17])
18</script>
19
20<template>
21  <div class="nova-lab">
22    <h1>NOVA LAB - Typowane Props</h1>
23    <ModuleCard
24      v-for="mod in modules"
25      :key="mod.id"
26      :module="mod"
27      :show-power="true"
28    />
29  </div>
30</template>
31
32<style scoped>
33.nova-lab {
34  background: #0a0e27;
35  color: #00ff88;
36  min-height: 100vh;
37  padding: 20px;
38  font-family: monospace;
39}
40h1 { color: #00ff88; margin-bottom: 15px; }
41</style>

Widzisz błąd w tej lekcji?

Sprawdź się

Odpowiedz na pytania z tej lekcji. Wybierz odpowiedź, a od razu zobaczysz, czy jest poprawna.

  1. 1. Która składnia definiuje typowane propsy w Vue 3 z TypeScript?

  2. 2. Jak oznaczyć prop jako opcjonalny w interfejsie TypeScript?

To 2 z 3 pytań do tej lekcji. Pozostałe rozwiążesz w grze.

Zadania praktyczne w grze

  • Edytor kodu

    Użyj withDefaults(defineProps<Props>(), { ... }) do ustawienia domyślnych wartości.

  • Układanie w poziomie

    Ułóż poprawną składnię withDefaults z defineProps:

  • Edytor kodu

    Użyj defineEmits<{}> do zdefiniowania zdarzenia 'command' z typowanymi argumentami.

Przydatne artykuły