3e étageTS TypeScriptPièce 6/7Avancé

TypeScript dans Vue et Nuxt

Utilise TypeScript dans un composant Vue avec script setup, type les props, les événements et les ref, et vérifie les types d'un projet Nuxt.

Ce que tu vas apprendre

  • Activer TypeScript dans un composant Vue.
  • Typer les props, les événements et les ref.
  • Typer une récupération de données et vérifier les types d'un projet Nuxt.

Activer TypeScript dans un composant

Il suffit d'ajouter lang="ts" à la balise script.

app/components/RecetteCarte.vue
<script setup lang="ts">
import { ref } from 'vue'

const portions = ref(4)
</script>

<template>
  <p>{{ portions.toFixed(1) }} portions</p>
</template>

Avec cet attribut, le code du script et les expressions du template sont vérifiés. Dans le template, portions.toFixed(1) est reconnu comme un appel sur un nombre.

Dans un projet Nuxt, tu n'as pas besoin d'importer ref : Nuxt le fait pour toi.

Typer les props

Les props sont les données qu'un composant reçoit de son parent. Avec defineProps, tu en décris la forme par un type.

app/components/RecetteCarte.vue
<script setup lang="ts">
interface Props {
  titre: string
  duree?: number
}

const props = defineProps<Props>()
</script>

Ici, titre est obligatoire et duree facultative, donc de type number | undefined. Si un parent oublie titre ou passe un nombre, l'erreur apparaît dans l'éditeur.

Tu peux aussi écrire le type directement entre les chevrons, sans interface : defineProps<{ titre: string }>(). La documentation de Vue demande de choisir entre cette déclaration par type et la déclaration classique, sans mélanger les deux.

Des valeurs par défaut

Pour donner une valeur à une prop facultative, utilise withDefaults.

<script setup lang="ts">
interface Props {
  titre: string
  etiquettes?: string[]
}

const props = withDefaults(defineProps<Props>(), {
  etiquettes: () => ['maison']
})
</script>

Une valeur de type tableau ou objet se donne sous forme de fonction. Chaque composant obtient ainsi sa propre copie.

Depuis Vue 3.5, la déstructuration réactive des props peut remplacer withDefaults : const { titre, etiquettes = ['maison'] } = defineProps<Props>().

Typer les événements

Un composant prévient son parent avec un événement. defineEmits décrit les événements et ce qu'ils transportent.

<script setup lang="ts">
const emit = defineEmits<{
  choisir: [id: number]
  supprimer: []
}>()

emit('choisir', 12)
emit('choisir', 'douze') // Erreur
</script>

Chaque événement est suivi de la liste de ses arguments. Cette syntaxe courte existe depuis Vue 3.3.

Typer une ref

Une ref est une valeur réactive. Quand tu lui donnes une valeur de départ, son type est déduit.

import { ref } from 'vue'
import type { Ref } from 'vue'

const annee = ref(2026)                       // Ref<number>
const choix = ref<string | number>('facile')  // type explicite
const recette = ref<Recette>()                // Ref<Recette | undefined>

Sans valeur de départ, ref<Recette>() vaut Recette | undefined. Il faudra donc vérifier la présence de la valeur avant de t'en servir : c'est du narrowing.

Le type Ref s'importe avec import type, qui indique qu'il ne sert qu'aux types.

Typer les données récupérées

Pour une adresse de ton site, useFetch accepte un type générique qui décrit la réponse.

app/pages/recettes/index.vue
<script setup lang="ts">
interface Recette {
  id: number
  titre: string
}

const { data, status, error } = await useFetch<Recette[]>('/api/recettes')
</script>

<template>
  <ul v-if="data">
    <li v-for="recette in data" :key="recette.id">{{ recette.titre }}</li>
  </ul>
</template>

Dans le script, data est de type Ref<Recette[] | undefined>. Le v-if écarte le cas undefined avant la boucle.

D'après la documentation de Nuxt, useFetch peut aussi déduire le type de la réponse depuis ta route serveur. Le générique explicite sert quand cette déduction n'est pas disponible.

Le type annoncé n'est pas vérifié au moment de la réponse. Si ton API envoie un autre format, TypeScript ne le verra pas. Pour une source non maîtrisée, vérifie la donnée toi-même.

Vérifier les types d'un projet Nuxt

Par défaut, les commandes nuxt dev et nuxt build ne vérifient pas les types. Pour le faire, installe vue-tsc et lance la commande de contrôle.

npm install --save-dev vue-tsc typescript
npx nuxt typecheck

vue-tsc joue le rôle de tsc pour les fichiers .vue. Tu peux aussi activer la vérification pendant le développement ou le build dans le fichier de configuration.

nuxt.config.ts
export default defineNuxtConfig({
  typescript: {
    typeCheck: true
  }
})

La configuration TypeScript de Nuxt

Nuxt génère lui-même ses fichiers de configuration dans le dossier .nuxt. Il s'appuie sur eux : ne modifie pas directement le tsconfig.json de ton projet, passe par nuxt.config.ts.

Ces fichiers sont créés quand tu lances le serveur de développement, le build ou nuxt prepare.

Si tu migres un projet JavaScript, l'option typescript.strict: false désactive temporairement les vérifications strictes. Remets-la à la normale ensuite.

Un éditeur adapté

Dans VS Code, installe l'extension Vue - Official : elle fournit le typage dans les fichiers .vue. Elle remplace l'ancienne extension Vetur, à désactiver.

À retenir

  • lang="ts" sur la balise script active TypeScript dans un composant.
  • defineProps<Props>() type les props ; withDefaults ou la déstructuration donnent des valeurs par défaut.
  • defineEmits décrit chaque événement et ses arguments.
  • ref<T>() précise le type ; sans valeur de départ, il inclut undefined.
  • useFetch<Recette[]>(...) décrit la réponse, mais ne la vérifie pas à l'exécution.
  • npx nuxt typecheck contrôle les types, que nuxt dev et nuxt build ne font pas seuls.

Pour aller plus loin

Sources officielles

Ensuite

Projet
Lignes de code
Niveau
3e étage
Appartement
TypeScript
Pièce
6/7
Plan n°
ts/06.typescript-dans-vue-et-nuxt
Lignes de code · fiches rédigées à partir des documentations officielles, sources citées en bas de chaque page.