Ne vous trompez pas de type

Ne vous trompez pas de type
Alexandre P. dans Dev - mis à jour le 11-03-2025

Simplifiez votre TypeScript : pourquoi l'utilisation de Record<K,V> est préférable aux types intermédiaires superflus pour un code plus maintenable et robuste.

Loin de moi, l'idée de lyncher un confrère qui a voulu bien faire en rédigeant un article sur le typage Typescript. Ce dernier a voulu partager une optimisation de code dans un article Medium afin de réduire l'impact d'une PR qui s'étendait sur plusieurs fichiers. J'ai d'autant plus peur quand je vois la centaine de commentaires qui acclament cet article, j'espère vraiment que ce sont des bots parce que das le cas contraire, on a du soucis à se faire sur nos projets ! Je rédige donc cet article afin de vous montrer une approche plus pratique.

Quelque part, je comprends le besoin initial, on a tous, la phobie du merge conflict quand on travaille dans une grosse équipe, donc on fait le maximum pour réduire l'impact.

Pourtant, son approche ne me parait pas judicieuse et je vais vous expliquer pourquoi.

Disclaimer: N'allez surtout pas le harceler dans les commentaires, je pense qu'il a voulu bien faire et aider la communauté. Malheureusement, son manque d'expérience peut coûter cher à terme si vous optez pour son approche.

Je ne vais pas revenir sur son état de code initial qui était justement ce qu'il cherchait à optimiser, mais directement vous montrer le résultat final après refacto.

Voici le typage proposé

L'élémet qui nous intéresse, c'est la clé "reactions" dans le type FinalResponse.

// FinalResponse.ts
import { Reaction } from './Reaction'

type AllowedReactions =
  | 'likes'
  | 'unicorns'
  | 'explodingHeads'
  | 'raisedHands'
  | 'fire'

export type ReactionMap = {
  [key in AllowedReactions]: Reaction
}

export type FinalResponse = {
  totalScore: number
  headingsPenalty: number
  sentencesPenalty: number
  charactersPenalty: number
  wordsPenalty: number
  headings: string[]
  sentences: string[]
  words: string[]
  links: { href: string; text: string }[]
  exceeded: {
    exceededSentences: string[]
    repeatedWords: { word: string; count: number }[]
  }
  reactions: ReactionMap
}

Pourtant quand je lis cette approche, je trouve cela complexe et pas optimisé, la création d'un type supplémentaire ReactionMap me semble superflu.

J'aurais procédé de la sorte:

// FinalResponse.ts
import { Reaction } from './Reaction'

type AllowedReactions =
  | 'likes'
  | 'unicorns'
  | 'explodingHeads'
  | 'raisedHands'
  | 'fire'

export type FinalResponse = {
  totalScore: number
  headingsPenalty: number
  sentencesPenalty: number
  charactersPenalty: number
  wordsPenalty: number
  headings: string[]
  sentences: string[]
  words: string[]
  links: { href: string; text: string }[]
  exceeded: {
    exceededSentences: string[]
    repeatedWords: { word: string; count: number }[]
  }
  reactions: Record<AllowedReactions, Reaction>
}

Pourquoi privilégier un typage simple et lisible ?

  • Premièrement, il faut réduire au maximum le nombre de types intermédiaires (surtout quand on peut s'en passer)
  • Et parce que lorsque l'on na moins de types à maintenir et que chacun de ces types est correctement utilisé, cela réduit le scope du projet et le rend simple.

J'applique avec beaucoup de ferveur l'approche de Dijkstra qui dit que la simplicité est un prédicat de la fiabilité.

Ce n'est que lorsque vous manipulez des choses simples, que vous créez du code fiable, robuste!

N'essayez pas de produire quelque chose de confus et difficile à lire. Certains pensent que le code complexe est synonyme de maitrise, mais je suis persuadé qu'il reflète surtout une incompréhension de l'auteur.

#code#conseil

user picture

Alexandre P.

Développeur passionné depuis plus de 20 ans, j'ai une appétence particulière pour les défis techniques et changer de technologie ne me fait pas froid aux yeux.


Votre vie privée

Nous utilisons des cookies pour améliorer votre expérience sur notre site, analyser notre trafic et personnaliser les publicités. En cliquant sur "Accepter", vous consentez à l'utilisation de tous les cookies. Vous pouvez également choisir de refuser en cliquant sur le bouton "Refuser".