Typescript avancé avec instance (Partie 2)
Il est temps de continuer (et de terminer) notre tutoriel Typescript. Si vous avez manqué notre article précédent sur Typescript, voici notre introduction initiale à Typescript et la première partie de ce tutoriel, où je vais expliquer l’exemple de JavaScript que nous utilisons et les étapes que nous avons prises pour l’améliorer partiellement. Aujourd’hui, nous compléterons notre exemple en remplissant tout ce qui manque encore. En particulier, nous verrons d’abord comment créer des versions partielles de types d’autres types existants. Ensuite, nous verrons comment taper correctement le partage du stockage Redux en utilisant la Fédération de type, et nous discuterons des avantages de la Fédération de type. Enfin, je vais vous montrer comment créer une fonction polymorphe dont le type de retour dépend de ses paramètres.
Un bref aperçu de ce que nous avons fait jusqu’à présent… Dans la première partie de ce tutoriel, nous avons utilisé comme exemple de travail une partie du magasin Redux extrait de nelio content. Tout commence avec un code JavaScript simple qui doit être amélioré en ajoutant des types spécifiques pour le rendre plus robuste et compréhensible. Par exemple, nous définissons les types suivants: type postId = nombre; Type day = String; Type post = {id: postId; title: String; Author: String; Day: Day; status: String; isssticky: Boolean;}; Type status = {Post: dictionary ; Jours: dictionnaire ; }; Cela nous aide à comprendre en un coup d’oeil le type d’information utilisée dans nos magasins. Par exemple, dans ce cas particulier, nous pouvons voir que l’état de l’application stocke deux choses: une liste de messages (que nous indexerons par l’ID du message) et une structure appelée jours, qui renvoie une liste d’identificateurs de messages un jour donné. Nous pouvons également voir les propriétés (et leurs types spécifiques) qui se trouvent dans l’objet post.
Une fois ces types définis, nous modifions toutes les fonctions de l’exemple
Ils vont s’en sortir. Cette tâche simple convertit les signatures de la fonction d’opacité javascript: \/ \/ selectors Function getpost (State, id) {…} Fonction getpostsinday (State, Day) {…} \/ \/ Fonction d’action receivenewpost (Post) {…} Fonction updatepost (postId, attributes) {…} \/ \/ Réduire la fonction réduire (état, action) {…} Signature de la fonction de script d’interprétation automatique: \/ \/ fonction de sélection getpost (état, id: postId): Post | not defined {…} Fonction getpostsinday (Status: State, Day: Day): postId [] {…} Action Function receivenewpost (Post: Post): any {…} Fonction updatepost (postId: postId, attribut: any): any {…} Reduce Function Reducer (Status: State, action: any): Status {…} La fonction getpostsinday est un bon exemple de la façon dont Typescript peut améliorer la qualité du Code. Si vous regardez les correspondances Javascript, vous ne savez vraiment pas ce que la fonction retournera. Bien sûr, son nom peut suggérer le type de résultat (peut – être une liste de messages?), Mais vous devez examiner le code source de la fonction (qui peut également inclure des actions et des simplificateurs) pour être sûr (En fait, il s’agit d’une liste d’identification de message). Vous pouvez améliorer cette situation en nommant mieux les choses (par exemple getidsofpostsinday), mais rien n’élimine plus le doute que le type spécifique: postId [].
Donc, maintenant que vous avez compris la situation actuelle, il est temps d’aller de l’avant et de réparer tout ce que nous avons manqué la semaine dernière. En particulier, nous savons que vous devez saisir les propriétés de la propriété de la fonction updatepost et que vous devez définir le type d’action qui aura notre action (Notez que dans reducer, la propriété d’action est n’importe quel type à ce stade). Comment taper un objet qui est un sous – ensemble d’un autre objet nous permet de commencer par des choses simples. La fonction updatepost génère une action indiquant que nous avons l’intention de mettre à jour un
Titre de la carte d’identité de naissance. Voici à quoi il ressemble:
Fonction updatepost (postId: postId, attributes: any): any {return {type: ‘Update _ post’, postId, Attributes,};} Voici comment Reducer utilise les actions pour mettre à jour les messages dans notre magasin: fonction Reducer (Status: State, action: any): Status {\/… Switch (action.type) {\/… Case \
Mais quels sont les attributs spécifiques d’une action? De toute évidence, ils ressemblent à des messages parce qu’ils devraient écraser les attributs que nous pourrions trouver dans les messages: type Update = {type: ‘Update _ post’; postId: number; attributes: Post;}; Mais si nous essayons de l’utiliser, nous trouvons qu’il ne fonctionne pas: Const Post: Post = {id: 1, Title: ‘title’, Author: ‘Ruth’, Day: ‘2020 – 10 – 01’, Status: ‘Draft’, isssticky: false,}; Action constante: mise à jour = {type: ‘Update _ post’, postId: 1, attribut: {by: ‘Toni’,},}; Parce que nous ne voulons pas que l’attribut lui – même soit un poste; Nous voulons qu’il s’agisse d’un sous – ensemble des attributs Post (c’est – à – dire que nous ne voulons spécifier que les attributs de l’objet post à écraser).
Pour résoudre ce problème, utilisez le type d’utilitaire partial: type Update = {type: ‘Update _ post’; postId: number; attributes: Partial ; }; C’est tout! Ou alors? Il y a encore des erreurs dans le filtrage des propriétés explicites des fragments de code précédents parce que vous pouvez obtenir des erreurs d’exécution non testées par le compilateur de Typescript. C’est pourquoi: l’opération de déclaration des mises à jour post a deux paramètres, un ID Post et un ensemble de propriétés que nous voulons mettre à jour. Une fois que nous serons prêts à agir, le réducteur s’en occupera.
écraser les messages existants avec de nouvelles valeurs:
Objet du message: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re C’est la partie défectueuse de notre Code; L’attribut postId de l’opération peut avoir un ID pots X, et l’attribut ID dans l’attribut a un ID post différent y: Const action: updateportaction = {type: ‘Update _ post’, postId: 1, attribut: {id: 2, Author: ‘Toni’,},},}; Il s’agit évidemment d’une opération valide, de sorte que Typescript ne déclenche aucune erreur, mais nous savons qu’il ne devrait pas déclencher d’erreurs. L’attribut ID et l’attribut posid dans les attributs (le cas échéant) doivent avoir la même valeur, sinon notre opération n’est pas cohérente. Notre type d’action est inexact, car il nous permet de définir une situation impossible… Comment résoudre ce problème? C’est très simple: il suffit de changer ce type pour rendre pratiquement impossible une scène autrement impossible.
La première solution à laquelle je pense est de supprimer l’attribut posid de l’opération et d’ajouter l’attribut id: type Update = {type: ‘Update _ post’; attribut: Partial ; }; Fonction updatepost (postId: postId, attribut: Partial ): Mise à jour {renvoie {type: ‘Update _ post’, attributs: {attributs, id: postId,},};} Ensuite, mettez à jour la transmission pour qu’elle fonctionne. Propriétés. ID au lieu de l’opération. PostId trouve et écrase les messages existants. Malheureusement, cette solution n’est pas idéale parce que la propriété est \
Be:
Const Working action: update = {type: ‘Update _ post’, Property: {id: 1, Author: ‘Toni’,},}; Const failinaction: update = {type: ‘Update _ post’, attribut: {Author: ‘Toni’,},}; Par conséquent, si nous voulons que Typescript nous protège, nous devons spécifier les types aussi précisément que possible et nous assurer qu’ils produisent des états impossibles. Compte tenu de tout cela, nous n’avons que deux options disponibles: si nous avons un attribut postId (comme nous l’avons fait au début), l’objet attributs ne peut pas contenir l’attribut Id. D’autre part, si l’opération n’a pas d’attribut postId, l’attribut doit contenir l’attribut Id. La première solution peut être facilement spécifiée en utilisant un autre type d’utilitaire, omit, qui nous permet de créer de nouveaux types en supprimant les attributs des types existants:
Type Update = {type: ‘Update _ post’; postId: postId, attribut: Partial < Omit >; }; Travailler comme prévu: Const Working action: update = {type: ‘Update _ post’, postId: 1, attributes: {Author: ‘Toni’},}; Const failingaction: updateposition = {type: ‘Update _ post’, postId: 1, Property: {id: 1, Author: ‘Toni’},}; Pour la deuxième option, nous devons explicitement ajouter l’attribut ID au – dessus du type partiel Nous avons défini: Type Update = {type: ‘Update _ post’; Properties: part & {id: postId};}; Ceci donne une fois de plus les résultats attendus: Const Working action: update = {type: ‘Update _ post’, attributs: {id: 1, Author: ‘Toni’,},}; Const failinaction: update = {type: ‘Update _ post’, attribut: {Author: ‘Toni’,},}; Dans la section précédente, nous avons vu comment taper l’une des deux opérations du magasin. Faisons de même pour la deuxième action. Sachez que receivenewpost est comme suit: fonction receivenewpost (Post: Post): tout {renvoie {type: ‘receive _ new post’, Post,};} Les types peuvent être
Séparer un homme d’un autre. Dans notre exemple, les deux types d’opérations ont une propriété de type avec les valeurs receive _ New Post et updatepost pour la mise à jour de receivenewpostaction. Parce que nous savons que l’action doit être une action ou un exemple d’une autre action, les deux branches de l’interrupteur couvrent toutes les possibilités: ou l’action. Le type est receive _ new post ou update post. Par conséquent, le retour final est redondant et inaccessible. Supposons donc que le retour soit supprimé pour corriger cette erreur. Y a – t – il autre chose que de supprimer le Code inutile? La réponse est oui. Si nous ajoutons maintenant un nouveau type d’action au Code: action de type = | updateaction | receivenewpostaction | newfeatureaction; Tapez newfeatureaction = {type: ‘New Features’; \/…}; Soudain, l’instruction Switch dans notre réducteur ne couvre plus tous les scénarios possibles: réducteur de fonctions (état: état, action: action): état {\/… Switch (action.type) {cas \
Ce que j’a I est getpostsinday, dont le type de retour est une liste d’identification, Post: function getpostsinday (State: State, Day: Day): postId [] {return status. Days [Day]? []] Même si le nom indique qu’il peut renvoyer une liste de messages. Vous vous demandez pourquoi j’utilise un nom aussi trompeur? Imaginez le scénario suivant: supposons que vous vouliez que cette fonction renvoie une liste d’id de poste ou une liste de postes réels, selon la valeur d’un de ses paramètres. Un contenu similaire: Const id: postId [] = getpostsinday (‘2020 – 10 – 01’, ‘id’); Post Post Post: post [] = getpostsinday (‘2020 – 10 – 01’, ‘all’); Pouvons – nous le faire dans Typescript? Bien sûr que si! Sinon, pourquoi devrais – je poser cette question? Tout ce que nous avons à faire est de définir une fonction polymorphe dont le résultat dépend des paramètres d’entrée. Donc, nous voulons deux versions différentes de la même fonctionnalité. Si l’un des attributs est un ID de chaîne, une liste de postId doit être retournée. Si la même propriété est string all, l’autre propriété doit renvoyer la liste des messages. Créez – les: fonction getpostsinday (Status: State, Day: Day, mode: \
Augmentez la qualité de votre travail à un nouveau niveau. Bonne chance dans cette nouvelle aventure! Photo de Mike kenneally sur unsplash.