Cours Vue.js · Module 15: TypeScript et Nuxt

Typer les props

2 min de lecture
Dans cette leçon5

Dans le Laboratoire Quantique, chaque module de la station doit déclarer précisément quelles données il accepte. Dans Vue 3 avec TypeScript, on utilise la syntaxe générique defineProps<{}>() pour typer les props.

defineProps avec type générique

Au lieu d'une validation à l'exécution (objet avec type, required), on peut utiliser la syntaxe TypeScript :

1<script setup lang="ts">
2// Syntaxe générique - types vérifiés à la compilation
3const props = defineProps<{
4  title: string
5  count: number
6  isActive: boolean
7}>()
8</script>

C'est l'équivalent de la syntaxe traditionnelle :

1<script setup>
2// Ancienne syntaxe - validation à l'exécution
3const props = defineProps({
4  title: { type: String, required: true },
5  count: { type: Number, required: true },
6  isActive: { type: Boolean, required: true }
7})
8</script>

Extraire une interface

Quand un composant a beaucoup de props, il vaut mieux extraire une interface :

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

Le signe ? signifie que la prop est optionnelle - elle n'a pas besoin d'être transmise.

withDefaults

Les génériques de TypeScript ne permettent pas de définir des valeurs par défaut dans defineProps. C'est à ça que sert 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>

Maintenant props.variant vaudra 'primary' s'il n'est pas fourni.

Les types union dans les props

TypeScript permet de définir des types précis :

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>

Types de props complexes

Les props peuvent contenir des objets imbriqués et des tableaux :

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> est un type dictionnaire - un objet avec des clés de type chaîne et des valeurs de n'importe quel type.

Code de cette leçon : 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 - Props typées</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>

Tu as repéré une erreur dans cette leçon ?

Teste tes connaissances

Réponds aux questions de cette leçon. Choisis une réponse pour voir tout de suite si elle est correcte.

  1. 1. Quelle syntaxe définit des props typées dans Vue 3 avec TypeScript ?

  2. 2. Comment marque-t-on une prop comme optionnelle dans une interface TypeScript ?

Voici 2 des 3 questions de cette leçon. Réponds aux autres dans le jeu.

Tâches pratiques dans le jeu

  • Éditeur de code

    Utilise withDefaults(defineProps<Props>(), { ... }) pour définir des valeurs par défaut.

  • Tri horizontal

    Ordonne la syntaxe correcte de withDefaults avec defineProps :

  • Éditeur de code

    Utilise defineEmits<{}> pour définir un événement 'command' avec des arguments typés.