Fermer

juillet 24, 2019

Découverte de TypeScript pour les développeurs C #


Les développeurs de C # ont commencé à créer des applications avec TypeScript, qui permet le typage statique combiné à l’énorme écosystème de JavaScript.

Si vous avez déjà travaillé sur une application JavaScript à l’époque antérieure et n’avez jamais eu la possibilité de le faire. De même avec l'outillage moderne et l'écosystème, vous seriez surpris de constater à quel point les expériences de développement et de production sont différentes et immensément améliorées. C'est particulièrement le cas si vous venez d'un fond .NET et C #. C # est un langage de programmation polyvalent très productif. Aujourd'hui, vous pouvez créer des applications de jeux, Web, de bureau et mobiles avec C # s'exécutant sur .NET Core, Mono et divers autres environnements d'exécution disponibles. JavaScript offre généralement la même chose, mais le plus grand manque est le confort et la sécurité du typage statique.

Le typage statique nous permet de détecter de nombreuses erreurs de programmation typiques pendant la compilation au lieu de les remarquer au moment de l'exécution. Lorsque vous combinez ce fait avec une excellente prise en charge des outils et des éditeurs de code, vous obtenez une boucle de réaction beaucoup plus rapide, ce qui vous donne plus de chances de créer des applications plus robustes plus rapidement.

TypeScript vous donne Juste cela, et cela sans le meilleur de JavaScript: l’énorme écosystème! Tous les packages disponibles sur npm par exemple, peuvent être utilisés, même s'ils ne sont pas implémentés dans TypeScript. C’est énorme, et c’est possible grâce à l’un des principes fondamentaux de TypeScript: cela commence et se termine par JavaScript. Nous verrons bientôt un exemple de la façon dont cela est réellement possible dans la pratique.

Le but principal de ce billet est de vous aider à créer des applications avec TypeScript et de vous donner une idée de l’apparence de ce processus depuis le développement. la perspective. Il est vivement recommandé de jeter un coup d'œil sur «TypeScript in 5 Minutes» si vous n'avez aucune expérience préalable de TypeScript et de son fonctionnement à un niveau élevé.

Code, c'est plus que l'écriture.

Mon expérience prouve la citation de mon oncle Bob sur le rapport entre la lecture du code et l'écriture dépassant 10 pour 1. Il est donc juste d'évaluer et de voir la puissance de TypeScript en termes de lecture du code.

Clonons l'un des plus grands projets TypeScript à code source ouvert: Visual Studio Code . Ce que je cherche à comprendre ici, c’est d’apprendre comment implémenter une commande afin de l’exécuter via la palette de commandes Visual Studio Code. Une recherche rapide sur GitHub m'a permis d'obtenir le fichier blockCommentCommand.ts qui a révélé une classe qui implémentait une interface: editorCommon.ICommand . Obtenons l'aide de Visual Studio Code (méta!) Pour en savoir plus sur la définition de l'interface:

 Code Visual Studio: Définition Peek

 Code Visual Studio: Interface Définition Peek

Nous sommes directement à l'intérieur de l'interface et la partie la plus importante ici est l'explicite, à quel point le point d'extensibilité est-il apparent. Je veux comprendre cette interface plus loin cependant. Examinons donc la fonction getEditOperations () de l'interface et découvrez toutes ses implémentations:

 Code Visual Studio: trouver toutes les références

 Visual Code de studio: trouver toutes les références résultats

C'est vraiment sympa, et ce qui est vraiment bien ici, c'est que ce n'est pas une ficelle. C'est trouver toutes les implémentations de fonctions d'interface. La méthode sortLinesCommand me semble intéressante et je souhaite y plonger. Allons-y et commençons à le changer. La première chose que je remarque est l’aide fournie par l’éditeur de code.

 Code Visual Studio: public getEditOperations

Vous pouvez constater que toute cette aide en matière d’outils, qui provient de la puissance de Les capacités d’analyse statique du langage lui-même me permettent d’explorer très facilement une base de code inconnue et assez volumineuse. Telle est la proposition de valeur fondamentale de TypeScript.

Maintenant que nous comprenons la valeur principale du langage, examinons certains de ses aspects en examinant un exemple.

Exemple de demande

Voyons un exemple. application pour comprendre comment structurer la base de code avec TypeScript. Dans cet exemple, nous verrons:

  • Comment travailler avec des primitives TypeScript telles que Classes
  • Consommation de packages NPM implémentés en JavaScript pur
  • Exécution de l'application sur Node.js

La logique principale de l'application est autour de voter pour des sujets particuliers qui ont certaines options. J'ai structuré la logique de code de cette application dans le fichier domain.ts qui contient le contenu ci-dessous.

 import {v4 as uuid} de 'uuid';

classe d'exportation TopicOption {
  en lecture seule nom: string;
  readonly id: string;

  constructeur (nom: chaîne) {
    this.name = nom
    this.id = uuid ()
  }
}

interface gagnant {
  option en lecture seule: TopicOption;
  votes en lecture seule: nombre;
}

classe d'exportation Topic {
  en lecture seule nom: string;
  options en lecture seule: TopicOption [];
  votes privés en lecture seule: Carte ;

  constructeur (nom: chaîne, options: TopicOption []) {
    this.name = nom
    this.options = options;
    this._votes = nouvelle carte  ();
    options.forEach (option => {
      this._votes.set (option.id, 0);
    })
  }

  vote (optionId: string) {
    const votesCount = this._votes.get (optionId);
    if (votesCount! = non défini) {
      this._votes.set (optionId, votesCount + 1);
    }
  }

  getWinner (): Gagnant {
    const winner = [...this._votes.entries()] .sort ((a, b) => a [1]> b [1]? 1: -1) [0];
    option const = this.options.find (x => x.id == gagnant [0]);

    if (option == non défini) {
      throw "l'option n'a aucune chance de ne pas être définie ici";
    }

    revenir {
      option: option,
      votes: gagnant [1]
    };
  }
} 

Si vous avez un arrière-plan C #, ce code devrait être explicite. Cependant, il est utile de toucher spécifiquement à certains de ses aspects pour comprendre comment TypeScript nous permet de structurer notre code.

Dites «bonjour» aux classes

La ​​construction Class est au cœur du langage de programmation C # et c modéliser nos applications et concepts de domaine. TypeScript utilise le même concept de modélisation, qui est proche des classes dans ECMAScript 6 (ES6), mais avec quelques «filets de sécurité» supplémentaires essentiels.

Supposons ce qui suit:

 classe d'exportation Sujet {
  en lecture seule nom: string;
  options en lecture seule: TopicOption [];
  votes privés en lecture seule: Carte ;

  constructeur (nom: chaîne, options: TopicOption []) {
    this.name = nom
    this.options = options;
    this._votes = nouvelle carte  ();

    options.forEach (option => {
      this._votes.set (option.id, 0);
    })
  }

  // ...
} 

Quelques points à noter ici:

  • Nous pouvons avoir des champs en lecture seule et des champs privés, tout comme nous pouvons le faire en C #. C'est gros! Particulièrement dans les cas où nous commençons à faire circuler une instance d'une classe, nous voulons avoir la certitude que celle-ci restera intacte et n'entraînera aucune modification involontaire. private et en lecture seule les modificateurs d'accès nous permettent d'exprimer cette intention dans le code et permettent au compilateur de se protéger contre ces modifications involontaires.
  • Nous avons également la notion de constructeur. C'est encore une grande victoire, nous permettant d'exprimer ce qui constitue une instance de classe afin d'appliquer un certain niveau d'intégrité d'état à l'instance.

Structural Typing

Le système de types TypeScript est basé sur structural. en tapant . Cela signifie essentiellement qu'il est possible de faire correspondre les types en fonction de leurs signatures. Comme nous l'avons vu avec l'implémentation de la méthode getWinner () ci-dessus, la signature nous oblige à renvoyer l'interface Winner . Cependant, nous n'avons pas eu besoin de créer une classe qui implémente explicitement l'interface Winner . Au lieu de cela, il nous suffisait de créer un objet correspondant à la définition de l'interface:

 getWinner (): Winner {
  // ...

  revenir {
    option: option,
    votes: gagnant [1]
  };
} 

Cela est très efficace lors de l'implémentation de la logique, car il n'est pas nécessaire d'implémenter explicitement une interface. Cet aspect du langage nous protège également en cas de modification éventuelle de la signature de l'interface Winner . Prenons le changement suivant pour la signature de l'interface Winner en ajoutant une nouvelle propriété appelée margin .

 interface Winner {
  option en lecture seule: TopicOption;
  votes en lecture seule: nombre;
  marge en lecture seule: nombre;
} 

Dès que ce changement a été effectué, Visual Studio Code met en évidence un problème:

 Code Visual Studio: propriété "marge" manquante mais obligatoire dans le type "Winner"

Plus d'erreurs d'un milliard de dollars: Protection contre null et undefined

Vous n'aimez pas NullReferenceException lorsque travaillait avec C # ? Je peux t'entendre! Pas tellement, non? Eh bien, tu n'es pas seul. En fait, null références ont été identifiées comme une erreur d'un milliard de dollars . TypeScript nous aide également sur ce problème. En définissant l'indicateur de compilateur - strictNullChecks TypeScript ne vous permet pas d'utiliser null ou undefined comme valeurs, sauf indication explicite.

Dans notre exemple de renvoyer un gagnant de la méthode getWinner () nous verrions une erreur si nous attribuions null à la propriété option .

 ] Code Visual Studio: erreur liée à l’attribution de la valeur null à l’option

TypeScript fournit le même niveau de sécurité du compilateur pour tous les membres pertinents. Par exemple, nous pouvons voir que nous ne pouvons pas passer null ou undefined en tant que paramètre d'une méthode qui accepte une chaîne :

 Code Visual Studio: impossible de passer les valeurs null ou indéfinie en tant que paramètre à une méthode qui accepte une chaîne

Toutefois, il existe parfois des cas légitimes permettant de représenter une valeur sous la forme null ou indéfini . Dans ces circonstances, nous avons plusieurs façons de le signaler explicitement. Par exemple, vous pouvez marquer le type comme nullable en ajoutant ? à la fin du nom du membre:

 interface Winner {
  option lecture seule ?: TopicOption;
  votes en lecture seule: nombre;
} 

Cela nous permet de donner undefined comme valeur légitime à cette tâche ou d'omettre entièrement la tâche. Par exemple, les deux représentations ci-dessous sont correctes pour faire correspondre l'objet à l'interface Winner :

 return {
  option: non défini,
  votes: gagnant [1]
};

// ...

revenir {
  votes: gagnant [1]
}; 

TypeScript ne s'arrête pas là. Il vous aide également lorsque vous consommez un membre qui peut être null ou undefined . Par exemple, nous verrions une erreur comme ci-dessous si nous essayions de contacter les membres de la valeur TopicOption renvoyée par la méthode getWinner () :

 Code Visual Studio: objet n'est peut-être pas défini

Ce comportement de TypeScript nous oblige à prendre garde contre null et undefined . Une fois la vérification effectuée, le compilateur sera ravi d’avoir accès aux membres de TopicOption :

 Code Visual Studio: ID de TopicOption

 Visual Studio Code: TopicOption name

Utilisation d'un paquet JavaScript npm

Comme vous pouvez le voir dans le code ci-dessous, nous pouvons importer un paquet nommé uuid que nous avons installé via npm install uuid - -save .

 import {v4 comme uuid} de 'uuid'; 

Ce paquet est implémenté en JavaScript, mais nous sommes toujours en mesure de le consommer et d’obtenir l’outillage et le support de sécurité que nous obtenons pour Code TypeScript. Ceci est possible grâce à la notion de fichiers de déclaration TypeScript . C'est un sujet très approfondi, mais le meilleur conseil que je puisse donner ici est de vérifier la recherche de type TypeScript où vous pouvez trouver et installer les fichiers de déclaration.

 typesearch

L'exécution sur Node.js

TypeScript est compilé en JavaScript, ce qui signifie que nous pouvons exécuter nos applications partout où nous sommes en mesure d'exécuter JavaScript, tant que nous compilons notre code source d'une manière connue de la plate-forme d'exécution. comment interpréter. Cela signifie principalement cibler la version correcte ECMAScript via l'indicateur de compilateur cible et spécifier la génération de code de module pertinente via l'indicateur de compilation du module module

.

.

Voyons comment nous pouvons compiler cette petite logique de vote à exécuter sur Node.js . Le texte ci-dessous correspond au contenu de index.ts :

 import {Topic, TopicOption} de './domain';

sujets constants: Sujet [] = [
  new Topic("Dogs or cats?", [
    new TopicOption("Dogs"),
    new TopicOption("Cats")
  ]),
  nouveau sujet ("C # ou TypeScript?", [
    new TopicOption("C#"),
    new TopicOption("TypeScript"),
    new TopicOption("Both are awesomse!")
  ])
];

pour (soit i = 0; i < 100; i++) {
  const randomTopic = topics[Math.floor(Math.random() * topics.length)];
  const randomOption = randomTopic.options[Math.floor(Math.random() * randomTopic.options.length)];
  randomTopic.vote(randomOption.id);
}

topics.forEach(topic => {
  const gagnant = topic.getWinner ();
  console.log (`Le gagnant pour '$ {topic.name}' est: '$ {gagnant.option.name}' !!!`);
}) 

Vous pouvez considérer cette étendue de fichier comme la méthode Main () de votre application .NET Console. C'est là que vous allez rassembler toute votre application et l'exécuter correctement.

 Exécution de la demande

Conclusion

Je vous ai montré la partie visible de l'iceberg. La vérité est que TypeScript vous apporte bien plus que cela avec une poignée de caractéristiques de type avancées telles que Discriminated Unions et String Literal Types qui permettent de: modélisez des scénarios complexes de manière beaucoup plus expressive et sûre.

Plus d'informations sur TypeScript

Vous souhaitez en savoir plus sur l'utilisation de TypeScript? Découvrez ces articles liés:





Source link