Un guide pratique de TypeScript - Comment créer une application Pokedex en utilisant HTML, CSS et TypeScript

May 21, 2020☕ ☕ 13 min Follow me on Twitter

Subscribe to receive the free weekly article

TypeScript est un sur-ensemble qui doit être compilé en JavaScript simple. Il offre plus de contrôle sur votre code car il utilise des annotations de type, des interfaces, des classes et une vérification de type statique pour générer des erreurs au moment de la compilation. TypeScript aide à améliorer la qualité et la compréhensibilité du code, en particulier avec une grande base de code.

Dans ce guide pratique, je vais vous guider à travers TypeScript en apprenant d'abord toutes les bases nécessaires pour commencer avec ce super langage, puis terminer cet article en créant une application à partir de zéro en utilisant HTML, CSS et TypeScript.

Allons y

Qu'est-ce que TypeScript?

TypeScript est un langage de programmation orienté objet développé et maintenu par Microsoft. Il s'agit d'un sur-ensemble de JavaScript, ce qui signifie que tout code JavaScript valide s'exécutera également comme prévu dans TypeScript. Il possède toute la puissance de JavaScript et quelques fonctionnalités supplémentaires. Il doit être compilé en JavaScript pur pendant l'exécution, donc un compilateur est nécessaire pour récupérer le code JS.

TypeScript utilise un typage statique, ce qui signifie que vous pouvez affecter un type à une variable donnée lors de la déclaration. Et c'est quelque chose qui ne peut pas être fait avec JavaScript car c'est un langage typé dynamiquement, il ne connaît pas le type de données d'une variable jusqu'à ce qu'il affecte une valeur à cette variable au moment de l'exécution.

La vérification de type statique rend TypeScript génial car elle permet de générer une erreur au moment de la compilation si la variable n'est pas utilisée ou réaffectée avec une annotation de type différente. Cependant, l'erreur n'empêche pas l'exécution du code, le code JavaScript sera toujours généré.

La typage statique est facultative dans TypeScript et si aucun type n'est défini mais que la variable a une valeur, TypeScript déduira la valeur comme type. Et si la variable n'a pas de valeur, le type sera défini sur any par défaut.

Maintenant, commençons à utiliser TypeScript dans la section suivante pour le voir en action.

Configuration de TypeScript

Comme je l'ai dit plus tôt, TypeScript doit compiler en JavaScript simple, donc nous devons utiliser un outil pour faire la compilation. Et pour avoir accès a cet outil, vous devez d'abord installer TypeScript en exécutant cette commande sur le terminal.

  yarn add -g typescript

Ou si vous utilisez npm:

  npm install -g typescript

Notez qu'ici j'utilise l'indicateur -g pour installer TypeScript globalement afin d'y accéder de n'importe où.

En installant TypeScript, nous avons maintenant accès au compilateur et nous pouvons compiler notre code en JavaScript. Plus tard, nous y plongerons et ce qu'il fait, mais pour l'instant ajoutons un fichier de configuration à notre projet. Il n'est pas obligatoire d'avoir un fichier de configuration, mais dans de nombreux cas, il est utile de l'avoir car il nous permet de définir des ensembles de règles pour le compilateur.

Configuration de TypeScript avec tsconfig

tsconfig est un fichier JSON qui aide à configurer TypeScript. Avoir un fichier de configuration est préférable car cela permet de contrôler le comportement du compilateur. Et pour créer le fichier de configuration, vous devez d'abord créer un nouveau répertoire nommé Pokedex et naviguer dans la racine du dossier. Ensuite, ouvrez-le sur le terminal ou un IDE et exécutez cette commande pour générer un nouveau fichier de configuration TypeScript.

  tsc --init

Une fois le fichier généré, nous pouvons maintenant l'explorer sur un IDE.

  • tsconfig.json
{
    "compilerOptions": {
        "target": "es5",
        "module": "commonjs",
        "outDir": "public/js"
        "rootDir": "src",
        "strict": true,
        "esModuleInterop": true
        "forceConsistentCasingInFileNames": true
    },
    "include": ["src"]
}

Ce fichier de configuration est beaucoup plus détaillé que cela, j'ai supprimé les commentaires et les valeurs inutilisées pour le rendre facile à lire. Cela dit, nous pouvons maintenant décomposer ces valeurs, expliquer chacune d'elles et ce qu'elle fait.

  • target: il spécifie la version cible ECMAScript lors de la compilation du code TypeScript. Ici, nous ciblons es5 pour prendre en charge tous les navigateurs, vous pouvez le changer en ES6, ES3 (c'est la valeur par défaut si aucune cible n'est spécifiée), ES2020, etc.
  • module: il définit le module du code compilé. Le module peut être Common JS, ES2015, ES2020, etc.
  • outDir: il spécifie le répertoire de sortie du code compilé en JavaScript.
  • rootDir: il définit l'emplacement où se trouvent les fichiers TypeScript qui doivent être compilés.
  • include: il aide à définir quel répertoire doit être compilé car si vous n'avez pas cette valeur, le compilateur prendra chaque fichier .ts et le compilera en JavaScript même si un répertoire de sortie est défini.

Avec cela en place, nous pouvons maintenant plonger dans l'une des parties les plus importantes de TypeScript: les types

Les Types de TypeScript

Les types fournissent un moyen d'améliorer la qualité et la compréhensibilité du code car il définit le type des variables. Ils sont facultatifs et aident d'abord à définir ce qu'une variable donnée doit avoir comme valeur et permet également au compilateur de détecter les erreurs avant l'exécution.

TypeScript a plusieurs types tels que number, string, boolean, enum, void, null, undefined, any, never, array, et tuple. Nous ne verrons pas tous les types dans ce guide, mais gardez à l'esprit qu'ils existent.

Voyons maintenant quelques exemples des types de base TypeScript.

Les Types de base TypeScript

let foo: string = "test"
let bar: number = 1
let baz: string[] = ["This", "is", "a", "Test"]

Comme vous pouvez le voir ici, nous avons trois variables de types différents. foo attend une chaîne,bar, un nombre et baz, un tableau de chaînes. S'ils reçoivent autre chose que le type déclaré, une erreur sera générée par TypeScript.

Vous pouvez également déclarer baz comme ça: let baz: Array<string> = ["This", "is", "a", "Test"].

Maintenant, essayons de réaffecter l'une de ces variables et voyons comment se comporte TypeScript.

let foo: string = "test"
foo = 1
Type '1' is not assignable to type 'string'

TypeScript générera une erreur car nous avons déjà déclaré foo pour attendre une chaîne comme valeur. Et cette erreur est détectée au moment de la compilation, ce qui rend TypeScript génial et utile.

Avec TypeScript, les types peuvent être explicites comme nous l'avons fait ci-dessus, mais ils peuvent aussi être implicites. Il est préférable de définir explicitement le type d'une valeur donnée car cela aide le compilateur et le développeur qui héritera du code. Mais vous pouvez également déclarer des variables avec une annotation de type implicite.

let foo = "test"
let bar = 1
let baz = ["This", "is", "a", "Test"]

TypeScript essaiera ici d'interférer autant que possible pour vous donner une sécurité de frappe avec moins de code. Il prendra la valeur et la définira comme type pour la variable. Et rien ne changera concernant les erreurs.

Essayons de réaffecter ces variables pour voir ce qui va se passer.

foo = 7
bar = "updated"
baz = [2, true, "a", 10]

TypeScript interceptera les erreurs comme avant, même si les types de variables sont déclarés implicitement.

Type '7' is not assignable to type 'string'.
Type '"updated"' is not assignable to type 'number'.
Type 'true' is not assignable to type 'string'.

Lorsque vous traitez un objet de plusieurs propriétés, il peut être délicat et ennuyeux de définir les types. Mais heureusement, TypeScript a quelque chose pour vous aider avec ce cas d'utilisation. Attaquons donc les interfaces TypeScript et les alias de type dans la section suivante.

Interfaces et alias de type

Les interfaces et les alias de type aident à définir la forme d'une structure de données de type objet. Ils semblent identiques en ce qui concerne leur structure, mais gardez à l'esprit qu'ils sont différents. Cependant, le consensus parmi les développeurs est d'utiliser interface chaque fois que vous le pouvez car il est dans l'ensemble des règles par défaut tslint.

Maintenant, créons une interface et un type d'alias dans la section suivante pour les voir en action.

interface ITest {
  id: number;
  name?: string;
}

type TestType = {
  id: number,
  name?: string,
}

function myTest(args: ITest): string {
  if (args.name) {
    return `Hello ${args.name}`
  }
  return "Hello Word"
}

myTest({ id: 1 })

Comme vous pouvez le voir, la structure d'un interface et d'un alias de type ressemble à un objet JavaScript. Ils aident à définir la forme d'une donnée donnée avec TypeScript.

Notez qu'ici, j'utilise un champ facultatif name en ajoutant un point d'interrogation (?). Il permet de rendre la propriété facultative. Cela signifie que si aucune valeur n'est transmise à la propriété name, elle renverra undefined comme valeur.

Ensuite, nous utilisons l'interface ITest comme type pour l'argument reçu par la fonction myTest. Et comme pour les variables, les fonctions peuvent également être définies pour renvoyer un type spécifique. Et ici, la valeur de retour doit être une chaîne sinon une erreur sera retournée par TypeScript.

Jusqu'à présent, nous avons couvert toutes les connaissances de base nécessaires pour démarrer avec TypeScript. Maintenant, utilisons-le pour construire un Pokedex avec HTML et CSS.

Allons y

Créez une application Pokedex à l'aide de TypeScript

Le projet que nous allons construire récupérera les données distantes de l'API Pokemon et affichera chaque pokemon avec TypeScript.

Commençons donc par créer trois nouveaux fichiers à la racine du dossier Pokedex: index.html, public/style.css et src/app.ts. Et pour la configuration de TypeScript, nous utiliserons le même fichier tsconfig.json créé précédemment.

Passons maintenant à la partie balisage et ajoutons du contenu au fichier HTML.

Balisage

  • index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="public/style.css" />
    <title>TypeScript Pokedex</title>
  </head>
  <body>
    <main>
      <h1>Typed Pokedex</h1>
      <div id="app"></div>
    </main>
    <script src="public/js/app.js"></script>
  </body>
</html>

Comme vous pouvez le voir, nous avons un balisage relativement simple. Il y a cependant deux choses importantes à retenir: l'id app de la balise div qui sera utilisé pour ajouter le contenu à l'aide de TypeScript et la balise script qui pointe vers le dossier public et pour être précis le fichier JavaScript que TypeScript créera pour nous lors de la compilation.

Par ailleurs, le fichier CSS est un peu long, donc je ne le couvrirai pas pour ne pas vous faire perdre du temps et de rester concentré sur TypeScript. Cela dit, nous pouvons maintenant avancer et commencer à récupérer les données de l'API.

Récupérer et afficher des données à l'aide de TypeScript

Nous commençons la partie TS en sélectionnant l'id app qui est l'id de la div tag.

  • src/app.ts
const container: HTMLElement | any = document.getElementById("app")
const pokemons: number = 100

interface IPokemon {
  id: number;
  name: string;
  image: string;
  type: string;
}

Ici, nous avons une annotation de type qui n'a pas encore été couverte. Il s'agit d'un type d'union qui permet d'avoir des types alternatifs pour une variable donnée. Cela signifie que si container n'est pas de type HTMLElement, TypeScript vérifiera à nouveau si la valeur est égale au type après le symbole pipe (|) et ainsi de suite car vous pouvez avoir plusieurs types.

Ensuite, nous avons une interface IPokemon qui définit la forme d'un objet pokemon qui sera utilisé ensuite dans la fonction chargée d'afficher le contenu.

  • src/app.ts
const fetchData = (): void => {
  for (let i = 1; i <= pokemons; i++) {
    getPokemon(i)
  }
}

const getPokemon = async (id: number): Promise<void> => {
  const data: Response = await fetch(`https://pokeapi.co/api/v2/pokemon/${id}`)
  const pokemon: any = await data.json()
  const pokemonType: string = pokemon.types
    .map((poke: any) => poke.type.name)
    .join(", ")

  const transformedPokemon = {
    id: pokemon.id,
    name: pokemon.name,
    image: `${pokemon.sprites.front_default}`,
    type: pokemonType,
  }

  showPokemon(transformedPokemon)
}

La fonction fetchData nous permet de parcourir le nombre de pokemon à récupérer et pour chaque objet appeller getPokemon avec le numéro de pokemon.

La récupération des données peut prendre du temps, c'est pourquoi nous utilisons une fonction asynchrone qui retourne une Promise de type void. Ce dernier signifie que la fonction ne retournera pas de valeur.

Et une fois les données récupérées, nous pouvons maintenant créer un nouvel objet transformedPokemon qui reflète l'interface IPokemon, puis le passer comme argument à showPokemon().

  • src/app.ts
const showPokemon = (pokemon: IPokemon): void => {
  let output: string = `
        <div class="card">
            <span class="card--id">#${pokemon.id}</span>
            <img class="card--image" src=${pokemon.image} alt=${pokemon.name} />
            <h1 class="card--name">${pokemon.name}</h1>
            <span class="card--details">${pokemon.type}</span>
        </div>
    `
  container.innerHTML += output
}

fetchData()

Comme vous pouvez le voir, la fonction showPokemon reçoit en paramètre l'objet pokemon de type IPokemon et retourne void ou aucune valeur pour être précis. Il ajoutera simplement le contenu au fichier HTML à l'aide de l'id container (rappelez-vous, c'est la balise div).

Génial! nous avons maintenant fait beaucoup de choses, cependant, quelque chose manque encore car le fichier index.html n'affichera rien si vous essayez de le lancer dans le navigateur car TypeScript doit être compilé en JavaScript simple. Alors, faisons cela dans la section suivante.

Compiler TypeScript en JavaScript

Plus tôt dans ce tutoriel, nous avons installé le compilateur TypeScript qui permet de compiler le code TS en JavaScript. Et pour ce faire, vous devez parcourir la racine du projet et exécuter la commande suivante.

  tsc

Cette commande compilera chaque fichier avec l'extension .ts en JavaScript. Et comme nous avons un fichier tsconfig, le compilateur suivra les règles définies et compilera uniquement les fichiers TS situés dans le dossier src et mettra le code JS dans le répertoire public.

Le compilateur permet également de compiler un seul fichier.

  tsc myFile.ts

Et si vous ne spécifiez pas de nom après le fichier TS (myFile.ts), le fichier JS compilé prendra le même nom que le fichier TS.

Et si vous ne souhaitez pas exécuter la commande à chaque modification, ajoutez simplement un indicateur -w pour permettre au compilateur de continuer à surveiller une modification et recompilez le code si nécessaire.

  tsc -w

Et maintenant, si vous lancez le fichier index.html, vous verrez votre application Pokedex rendue avec succès dans le navigateur.

app

Génial! nous avons maintenant terminé l'apprentissage des bases de TypeScript en créant une application Pokedex avec HTML et CSS.

Prévisualisez le projet terminé ici ou trouvez le code source ici

Merci d'avoir lu.

Ressources

Voici quelques ressources utiles pour plonger plus profondément dans TypeScript.

Types TypeScript

Options du compilateur TypeScript

Manuel TypeScript

#typescript#html#css

Support my work

Get articles in your inbox