# TypeScript Support

Vue CLI (opens new window) provides built-in TypeScript tooling support.

# Déclaration officielle dans les paquets NPM

Un système de types statiques peut aider à prévenir de nombreuses erreurs d'exécution potentielles au fur et à mesure que les applications se développent, c'est pourquoi Vue 3 est écrit en TypeScript. Cela signifie que vous n'avez pas besoin d'outils supplémentaires pour utiliser TypeScript avec Vue - il bénéficie d'un support citoyen de première classe.

// tsconfig.json
{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    // this enables stricter inference for data properties on `this`
    "strict": true,
    "jsx": "preserve",
    "moduleResolution": "node"
  }
}
1
2
3
4
5
6
7
8
9
10
11

Notez que vous devez inclure strict : true (ou au moins noImplicitThis : true qui est une partie du drapeau strict) pour tirer parti de la vérification du type de this dans les méthodes des composants, sinon il est toujours traité comme un type any.

Voir TypeScript compiler options docs (opens new window) pour plus de détails.

# Configuration de Webpack

Si vous utilisez une configuration Webpack personnalisée, ts-loader doit être configuré pour analyser les blocs <script lang="ts"> dans les fichiers .vue :










 









// webpack.config.js
module.exports = {
  ...
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        loader: 'ts-loader',
        options: {
          appendTsSuffixTo: [/\.vue$/],
        },
        exclude: /node_modules/,
      },
      {
        test: /\.vue$/,
        loader: 'vue-loader',
      }
      ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# Outil de développement

# Création de projets

Vue CLI (opens new window) peut générer de nouveaux projets qui utilisent TypeScript. Pour commencer :

# 1. Installez Vue CLI, s'il n'est pas déjà installé.
npm install --global @vue/cli

# 2. Créez un nouveau projet, puis choisissez l'option "Sélectionner manuellement les caractéristiques".
vue create my-project-name

# Si vous avez déjà un projet Vue CLI sans TypeScript, veuillez ajouter un plugin Vue CLI approprié :
vue add typescript
1
2
3
4
5
6
7
8

Assurez-vous que la partie script du composant a TypeScript comme langage :

<script lang="ts">
  ...
</script>
1
2
3

# Support de l'éditeur

Pour le développement d'applications Vue avec TypeScript, nous vous recommandons vivement d'utiliser Visual Studio Code (opens new window), qui offre une excellente prise en charge immédiate de TypeScript. Si vous utilisez des single-file components (SFCs), procurez-vous l'impressionnante extension Vetur (opens new window), qui fournit l'inférence TypeScript dans les SFCs et bien d'autres fonctionnalités.

WebStorm (opens new window) fournit également un support prêt à l'emploi pour TypeScript et Vue.

# Définir les composants Vue

Pour permettre à TypeScript de déduire correctement les types dans les options des composants Vue, vous devez définir les composants avec la méthode globale defineComponent :

import { defineComponent } from 'vue'

const Component = defineComponent({
  // inférence de type activée
})
1
2
3
4
5

# Utilisation avec l'API Options

TypeScript devrait être capable de déduire la plupart des types sans avoir à les définir explicitement. Par exemple, si vous avez un composant avec une propriété numérique count, vous aurez une erreur si vous essayez d'appeler une méthode spécifique aux chaînes de caractères sur celui-ci :

const Component = defineComponent({
  data() {
    return {
      count: 0
    }
  },
  mounted() {
    const result = this.count.split('') // => La propriété 'split' n'existe pas sur le type 'number'.
  }
})
1
2
3
4
5
6
7
8
9
10

Si vous disposez d'un type ou d'une interface complexe, vous pouvez le caster en utilisant type assertion (opens new window) :

interface Book {
  title: string
  author: string
  year: number
}

const Component = defineComponent({
  data() {
    return {
      book: {
        title: 'Vue 3 Guide',
        author: 'Vue Team',
        year: 2020
      } as Book
    }
  }
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# Annotation des types de retour

En raison de la nature circulaire des fichiers de déclaration de Vue, TypeScript peut avoir des difficultés à déduire les types de propriétés calculées. Pour cette raison, vous pouvez avoir besoin d'annoter le type de retour des propriétés calculées.

import { defineComponent } from 'vue'

const Component = defineComponent({
  data() {
    return {
      message: 'Hello!'
    }
  },
  computed: {
    // a besoin d'une annotation
    greeting(): string {
      return this.message + '!'
    }

    // dans un compute avec un setter, le getter doit être annoté
    greetingUppercased: {
      get(): string {
        return this.greeting.toUpperCase();
      },
      set(newValue: string) {
        this.message = newValue.toUpperCase();
      },
    },
  }
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# Annoter les props

Vue fait une validation à l'exécution sur les props avec un type défini. Pour fournir ces types à TypeScript, nous devons caster le constructeur avec PropType :

import { defineComponent, PropType } from 'vue'

interface Book {
  title: string
  author: string
  year: number
}

const Component = defineComponent({
  props: {
    name: String,
    success: { type: String },
    callback: {
      type: Function as PropType<() => void>
    },
    book: {
      type: Object as PropType<Book>,
      required: true
    }
  }
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

WARNING

En raison d'une limitation de conception (opens new window) dans TypeScript lorsqu'il s'agit de l'inférence de type des expressions de fonction, vous devez faire attention aux valeurs validators et default pour les objets et les tableaux :

import { defineComponent, PropType } from 'vue'

interface Book {
  title: string
  year?: number
}

const Component = defineComponent({
  props: {
    bookA: {
      type: Object as PropType<Book>,
      // Assurez-vous d'utiliser les fonctions de flèche
      default: () => ({
        title: 'Arrow Function Expression'
      }),
      validator: (book: Book) => !!book.title
    },
    bookB: {
      type: Object as PropType<Book>,
      // Ou fournir un paramètre this explicite
      default(this: void) {
        return {
          title: 'Function Expression'
        }
      },
      validator(this: void, book: Book) {
        return !!book.title
      }
    }
  }
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

# Annoter les émetteurs

Nous pouvons annoter une charge utile pour l'événement émis. De plus, tous les événements émis non déclarés produiront une erreur de type lorsqu'ils seront appelés :

const Component = defineComponent({
  emits: {
    addBook(payload: { bookName: string }) {
      // perform runtime validation      // effectuer la validation de l'exécution

      return payload.bookName.length > 0
    }
  },
  methods: {
    onSubmit() {
      this.$emit('addBook', {
        bookName: 123 // Erreur de type !
      })

      this.$emit('non-declared-event') // Erreur de type !
    }
  }
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# Utilisation avec l'API de composition

Dans la fonction setup(), vous n'avez pas besoin de passer un type au paramètre props car il déduira les types de l'option du composant props.

import { defineComponent } from 'vue'

const Component = defineComponent({
  props: {
    message: {
      type: String,
      required: true
    }
  },

  setup(props) {
    const result = props.message.split('') // correct, 'message' est tapé comme une chaîne de caractères.
    const filtered = props.message.filter(p => p.value) // une erreur sera déclenchée : La propriété 'filter' n'existe pas sur le type 'string'.
  }
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# Typage des `refs'.

Les références déduisent le type à partir de la valeur initiale :

import { defineComponent, ref } from 'vue'

const Component = defineComponent({
  setup() {
    const year = ref(2020)

    const result = year.value.split('') // => La propriété 'split' n'existe pas sur le type 'number'.
  }
})
1
2
3
4
5
6
7
8
9

Parfois, nous pouvons avoir besoin de spécifier des types complexes pour la valeur interne d'un ref. Pour ce faire, il suffit de passer un argument générique lors de l'appel de ref pour remplacer l'inférence par défaut :

const year = ref<string | number>('2020') // le type de l'année: Ref<string | number>

year.value = 2020 // ok!
1
2
3

Note

Si le type du générique est inconnu, il est recommandé de convertir ref en Ref<T>.

# Typing reactive (typage)

Lorsque l'on tape une propriété reactive, on peut utiliser des interfaces :

import { defineComponent, reactive } from 'vue'

interface Book {
  title: string
  year?: number
}

export default defineComponent({
  name: 'HelloWorld',
  setup() {
    const book = reactive<Book>({ title: 'Vue 3 Guide' })
    // or
    const book: Book = reactive({ title: 'Vue 3 Guide' })
    // or
    const book = reactive({ title: 'Vue 3 Guide' }) as Book
  }
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# Typage de computed.

Les valeurs calculées déduiront automatiquement le type de la valeur retournée.

import { defineComponent, ref, computed } from 'vue'

export default defineComponent({
  name: 'CounterButton',
  setup() {
    let count = ref(0)

    // en lecture seule
    const doubleCount = computed(() => count.value * 2)

    const result = doubleCount.value.split('') // => La propriété 'split' n'existe pas sur le type 'number'.
  }
})
1
2
3
4
5
6
7
8
9
10
11
12
13

Deployed on Netlify.
Dernière Mise-à-jour: 11/20/2021, 10:06:27 AM