Fermer

mars 12, 2024

Vue 3 avec TypeScript Jump-Start

Vue 3 avec TypeScript Jump-Start


Ce sont les concepts que vous devez connaître lorsque vous démarrez votre parcours Vue 3 + TypeScript.

Vue 3 a une longueur d’avance sur son prédécesseur en termes de facilité d’utilisation et de compatibilité avec TypeScript. Cependant, parfois les informations sur le clé les choses à savoir et à commencer peuvent être un peu difficiles à digérer.

Dans cet article, mon objectif est d’expliquer et de lister les concepts qui me semblent les plus courants et les plus pertinents à garder à l’esprit lorsque vous démarrez votre voyage Vue 3 + TS. Veuillez noter qu’il ne s’agit pas d’un didacticiel TypeScript et je supposerai une connaissance de base du langage.

Les outils et la configuration de TypeScript sont un véritable terrier de lapin et on pourrait probablement écrire non pas un, mais plusieurs articles approfondis sur la façon de mettre en place un projet pour une intégration parfaite entre les deux.

Cependant, je pense qu’il y a un piège important que je souhaite mentionner avant de commencer avec le véritable TS, à savoir Le mode de prise de contrôle de Volar.

Je suppose que vous utiliserez Volar et VS Code ici. Si vous utilisez un outil différent, vous pouvez passer en toute sécurité à la section suivante.

Épargnez-vous quelques maux de tête maintenant et suivez le lien ci-dessus pour obtenir la documentation sur la configuration du mode de prise de contrôle : c’est pas évident il faut configurer VS Code comme celui-ci pour que Volar fonctionne correctement avec TypeScript.

Une fois que vous avez terminé, assurez-vous également de vérifier que la version TypeScript utilisée par Volar est la bonne. même comme votre colis. Cette inadéquation peut rapidement créer des problèmes lors de l’exécution de vérifications de type dans CI ou en dehors de votre environnement de développement personnel.

Vous souhaiterez sélectionner « Utiliser la version de l’espace de travail » à moins que vous ne soyez sûr à 100 % de vouloir une version alimentant Volar différente de celle utilisée par votre espace de travail.

Travailler avec l’API d’options

Lorsque vous travaillez avec des composants créés avec l’API Options, vous souhaiterez importer et utiliser le defineComponent assistant de Vue pour s’assurer que le composant est correctement saisi lorsqu’il est importé dans d’autres fichiers.

<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
  
})
</script>

Vous n’en avez pas besoin lorsque vous utilisez script setup sucre, car il sera déjà saisi correctement pour vous.

Accessoires de frappe

Taper correctement les accessoires de vos composants est sans doute l’une des parties les plus importantes de l’utilisation de TS avec Vue 3. Cela garantira la sécurité du type même au sein de votre template balises, alors comment pouvons-nous saisir des choses ?

<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
  props: {
    someNumber: { type: Number, default: 0 },
    user: { type: Object, default: 0 }
  }
})
</script>

<script setup lang="ts">
defineProps({
  someNumber: { type: Number, default: 0 },
  user: { type: Object, default: 0 }
})
</script>

Dans l’exemple ci-dessus, nous avons à la fois l’API Options et l’API Composition définissant exactement les mêmes accessoires sans aucun type particulier de types TS. Ils créent tous les deux un someNumber prop qui est tapé sur un Number et un user tapé dans un générique Object.

Lorsqu’il s’agit de primitives comme number, boolean, stringnous n’avons pas vraiment besoin de faire quoi que ce soit pour indiquer à TypeScript le type de l’accessoire car il sera déduit par le type que Vue fournit, comme dans le cas de someNumber.

Cependant, nous souhaitons probablement utiliser un type plus spécifique pour notre accessoire utilisateur.

Je suppose que nous avons défini le type suivant :

interface User {
  id: number
  name: string
}

Maintenant, nous pouvons utiliser le type spécial PropType que Vue propose pour définir plus spécifiquement ce que cela Object dans user est.

<script lang="ts">
import { defineComponent, PropType } from 'vue'
export default defineComponent({
  props: {
    someNumber: { type: Number, default: 0 },
    user: { type: Object as PropType<User>, default: 0 }
  }
})
</script>

<script setup lang="ts">
import { PropType } from 'vue'
defineProps({
  someNumber: { type: Number, default: 0 },
  user: { type: Object as PropType<User>, default: 0 }
})
</script>

La saisie émet

Maintenant que nous avons les accessoires correctement saisis, nous voulons nous assurer que notre emits sont également strictement typés afin que Volar et TypeScript puissent nous aider à vérifier que nous utilisons correctement les charges utiles d’émission.

<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
  emits: ['userSelected', 'click']
})
</script>

<script setup lang="ts">
defineEmits(['userSelected', 'click'])
</script>

Dans l’exemple ci-dessus, nous voyons à nouveau des exemples d’API d’options et d’API de composition sur la façon de définir emits dans un composant. Nous choisissons d’utiliser la version abrégée d’emits (il existe une version plus longue qui permet de valider la sortie de la même manière que fonctionnent les accessoires).

Le problème en le laissant ainsi lors de l’utilisation de TypeScript est que le contenu du emit sera supposé être any, ce qui n’est pas très utile. Allons-y et tapons correctement ces émissions.

Nous supposerons que le click l’événement n’émet pas de charge utile, et le userSelected passera un objet utilisateur.

<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
  emits: {
    // eslint-disable-next-line
    'userSelected': (user: User) => true,
    // eslint-disable-next-line
    'click': () => true
  }
})
</script>

<script setup lang="ts">
defineEmits<{
  'userSelected': [user: User]
  'click': []
}>()
</script>

Il y a quelques éléments qui méritent d’être dévoilés dans cet exemple. Commençons par l’API Options.

Le emits La propriété est désormais un objet, au lieu d’un tableau de chaînes. Il s’agit d’une manière étendue de définir les émissions, où chaque émission déclare une fonction qui fonctionne comme une validation, similaire à la validator propriété dans props. J’ai choisi de revenir true car nous n’avons pas besoin de valider l’émission, puisque TypeScript est probablement une validation suffisante – cela dépend entièrement de vous.

Le paramètre trouvé dans la fonction de validation sera supposé par TypeScript comme étant la charge utile du emitalors maintenant, quand nous avons un composant à l’écoute du userSelected événement, TypeScript saura que nous attendons un User.

Notez que j’ai ajouté une désactivation sur ESLint sur les deux lignes. En fonction de vos règles ESLint, cela peut ne pas être nécessaire, mais avec les règles recommandées par défaut de Vue, vous obtiendrez une erreur sur la fonction puisque le user le paramètre n’est pas utilisé. Nous n’en avons pas besoin pour click techniquement, mais c’est devenu une de mes habitudes de l’ajouter partout pour éviter les maux de tête.

La version de l’API Composition est également un peu différente. Notez que la déclaration réelle des émissions n’est plus un paramètre à l’intérieur du defineEmits fonction, mais plutôt une variable de type. Alors maintenant, il vit dans le <{}> avant le ().

Nous définissons nos émissions en définissant une propriété comme userSelected puis avec une syntaxe de tuple, nous déterminons la charge utile. De sorte que [user: User] signifie que nous aurons un user charge utile avec un User taper. Une fois de plus, cela permettra à TypeScript de déterminer la charge utile à laquelle nous pouvons nous attendre dans un autre composant lors de l’écoute de cet événement particulier.

Types remarquables

Quelques types que vous allez utiliser beaucoup (vous les importez depuis 'vue') sont:

Réf

Une référence, comme lors de la création d’une valeur de référence d’API de composition comme dans :

const user = ref({ id: 123, name: 'Marina' })

Dans des cas comme celui-ci, vous souhaiterez peut-être taper strictement votre référence, de sorte qu’au lieu que TS suppose qu’il s’agit d’un objet avec un identifiant et un nom, ce soit un type User.

const user: Ref<User> = ref({ id: 123, name: 'Marina' })

Noter que Ref peut également accepter ComputedRef types, de sorte que si vous avez une fonction où vous attendez une référence ou une valeur calculée, vous pouvez l’utiliser en toute sécurité Ref.

const myFn = (param: Ref) => { 
    return param.value // .value is defined as it exists in both computed and ref 
}

Peut-êtreRéf

Si vous écrivez beaucoup de composables, vous pourriez vous retrouver à utiliser des fonctions d’assistance telles que unref beaucoup puisque nous ne savons pas si notre utilisateur va transmettre une valeur brute ou une référence. Dans ces cas, nous pouvons utiliser le MaybeRef taper.

export default (val: MaybeRef<boolean>) => {
   const rawBool = unref(val)
}

ComposantInstancePublic

Lors de la saisie d’un modèle refvous souhaiterez utiliser soit ComponentPublicInstance pour le taper comme n’importe quel générique component.

<template>
  <p ref="myP">Example</p>
  <SomeComponent ref="myComp" />
</template>

<script setup lang="ts">
import { Ref } from 'vue'

const myP: Ref<HTMLElement|null> = ref(null)
const myComp: Ref<ComponentPublicInstance|null> = ref(null)

const doSomething = () => {
  // TS knows about $el because its a ComponentPublicInstance
  myComp.value?.$el
}
</script>

Si vous avez besoin d’accéder à des méthodes spécifiques dans la référence du composant, vous devrez toutefois utiliser InstanceType pour le définir au lieu de ComponentPublicInstance.

<template>
  <p ref="myP">Example</p>
  <SomeComponent ref="myComp" />
</template>

<script setup lang="ts">
import { Ref } from 'vue'

const myP: Ref<HTMLElement|null> = ref(null)
const myComp: Ref<InstanceType<typeof SomeComponent>|null> = ref(null)

const doSomething = () => {
  // TS knows about myMethod inside of `SomeComponent`
  myComp.value?.myMethod()
}
</script>

Déclaration des composants globaux

Lorsque nous utilisons des composants globaux qui ne sont pas spécifiquement importés dans nos composants, nous devons les déclarer quelque part pour que TypeScript fonctionne.

Dans global.d.ts vous pouvez ajouter la déclaration suivante avec vos composants globaux selon vos besoins. J’ai ajouté un exemple avec RouterLink et RouterView de Vue Router car ils sont couramment utilisés comme composants globaux.

import BaseCheckbox from './globals/BaseCheckbox.vue'

declare module '@vue/runtime-core' {
  export interface GlobalComponents {
    RouterLink: typeof import('vue-router')['RouterLink']
    RouterView: typeof import('vue-router')['RouterView']

    // Custom components example
    BaseCheckbox: typeof BaseCheckbox
  }
}

Emballer

Cela ne fait qu’effleurer la surface de l’intégration de TS avec Vue 3, mais j’espère que ces sujets clés incontournables vous aideront à démarrer rapidement et efficacement votre parcours TS-Vue 3.




Source link