Ton langage coûte des tokens : ce que l'IA écrit le mieux
Quand une partie de ton code est écrite par une IA, ton langage de programmation n'est plus seulement une affaire de goût ou de recrutement. Il a un coût direct : chaque acrobatie syntaxique que le modèle doit résoudre se paie en tokens — l'unité de calcul et de facturation des modèles — et chaque ligne difficile à relire se paie en temps humain. Steve Yegge, co-auteur avec Gene Kim du livre « Vibe Coding » (IT Revolution, fin 2025), rapporte avoir généré de l'ordre d'un million de lignes de code en un an avec des essaims d'agents. Son retour d'expérience : TypeScript se révèle coûteux à l'usage intensif, parce que les modèles brûlent une part disproportionnée de tokens à résoudre des types complexes ou à fabriquer des échappatoires syntaxiques. À l'inverse, il décrit Go comme un excellent langage d'infrastructure pour le vibecoding : syntaxe lisible, prévisible, sans fioritures, facile à relire pour l'humain qui vérifie. La leçon n'est pas « réécris tout en Go ». Elle est plus utile que ça : pour un nouveau service, « facile à relire, prévisible pour le modèle » est devenu un critère de stack aussi légitime que l'écosystème ou l'embauche.
Un million de lignes plus tard : le constat de Yegge
Steve Yegge n'a pas testé trois prompts un dimanche. Avec Gene Kim, il a co-écrit « Vibe Coding » (IT Revolution, fin 2025), et il travaille avec des essaims d'agents : plusieurs agents de code qui tournent en parallèle sur les mêmes projets. À cette échelle — il parle d'un ordre de grandeur d'un million de lignes générées en un an — les frictions ne sont plus des anecdotes. Ce sont des patterns.
Et le pattern qu'il remonte est contre-intuitif : TypeScript, pourtant le choix par défaut de beaucoup d'équipes web, est le langage qui fait le plus transpirer les agents. Pas parce qu'il est mauvais. Parce que son système de types, très puissant, crée des situations où le modèle tourne en rond.
Pourquoi TypeScript fait brûler des tokens
Un agent qui écrit du TypeScript doit satisfaire le compilateur. Sur des types simples, aucun souci. Mais dès que le projet accumule des generics imbriqués, des types conditionnels ou de la métaprogrammation de types, le modèle entre dans une boucle coûteuse : il propose du code, le compilateur râle, il corrige, ça râle encore. Chaque tour de boucle, ce sont des tokens.
Voilà le genre de code qui déclenche la boucle :
type ApiResponse<T> = T extends { data: infer D }
? { ok: true; payload: D }
: { ok: false; error: string };
Élégant pour l'humain qui l'a conçu. Piégeux pour un modèle qui doit produire du code compatible avec ce type dans vingt fichiers.
Et quand le modèle n'y arrive pas, Yegge décrit le second comportement : il fabrique des échappatoires.
// @ts-ignore
const user = response as any as User;
Double peine : tu as payé les tokens de la bataille perdue, et tu récupères un contournement silencieux qui neutralise ce que ton typage était censé garantir.
Précision importante : le problème n'est pas TypeScript en soi, c'est la sophistication du typage. Du TypeScript avec des types plats et explicites reste tout à fait praticable pour un agent.
Ce que Go fait de bien
Yegge décrit Go comme un excellent langage d'infrastructure pour le vibecoding, et ses raisons tiennent en trois mots : lisible, prévisible, sans fioritures.
func (s *Store) GetUser(ctx context.Context, id string) (*User, error) {
var u User
err := s.db.QueryRowContext(ctx,
"SELECT id, email FROM users WHERE id = $1", id,
).Scan(&u.ID, &u.Email)
if err != nil {
return nil, fmt.Errorf("get user %s: %w", id, err)
}
return &u, nil
}
Ce code est ennuyeux. C'est exactement le but. En Go, il existe en général une seule façon idiomatique d'écrire quelque chose, gofmt impose un formatage unique, et les erreurs se gèrent explicitement, ligne par ligne. Résultat :
- le modèle a moins de choix à faire, donc moins d'occasions d'improviser ;
- toi, tu peux relire vite — et c'est le point clé, parce que quand l'IA écrit, ton travail se déplace de l'écriture vers la relecture.
Un langage « ennuyeux » n'est plus un défaut. C'est une propriété recherchée : ta capacité à vérifier ce que l'IA a produit dépend directement de la facilité à relire son code.
Les quatre critères IA d'une stack
Au-delà du duel TypeScript/Go, tu peux évaluer n'importe quel langage ou framework sur quatre axes dès qu'une partie du code sera générée :
- Relisibilité humaine. Tu vas relire beaucoup plus que tu n'écris. Un code qui se relit vite, c'est de la vérification qui coûte moins cher.
- Prévisibilité pour le modèle. Moins il existe de façons d'écrire la même chose, moins le modèle improvise. Les conventions fortes canalisent la génération : l'IA suit les rails.
- Verbosité, donc coût par fonctionnalité. Chaque token généré se paie. À fonctionnalité égale, un framework qui exige trois fichiers de configuration coûte plus cher qu'un qui n'en demande aucun. Attention à ne pas confondre verbosité et lisibilité : Go est un peu verbeux mais très lisible, et c'est un bon compromis.
- Stabilité de l'écosystème. Un écosystème qui casse son API tous les six mois pousse le modèle à mélanger les versions qu'il a vues à l'entraînement. Moins de versions divergentes, c'est moins de code qui appelle des fonctions qui n'existent plus.
Un framework à conventions fortes — le fameux « convention over configuration » — coche souvent trois de ces cases d'un coup.
On ne réécrit rien
Disons-le clairement : ces critères ne justifient pas de réécrire une app existante. Ton code en production a une valeur que des tokens économisés ne compensent pas : il est testé, débuggé, connu de ton équipe. Réécrire pour « optimiser les tokens », c'est détruire ce capital pour un gain marginal.
Le critère devient légitime au moment d'un vrai choix : un nouveau service, un nouveau projet, une brique d'infrastructure séparée. À ce moment-là, tu pèses déjà l'écosystème, le recrutement, la maturité des libs. « Coût et fiabilité de la génération IA » entre simplement dans la balance, au même rang que les autres. Pas au-dessus : si ton équipe vit dans npm et que ton produit dépend de React, un backend TypeScript sobre et bien conventionné reste un choix rationnel.
Par où commencer
Pas besoin de changer de stack demain. Voilà des actions concrètes, par ordre d'effort :
- Si tu restes en TypeScript : garde des types simples et explicites, bannis la métaprogrammation de types du code applicatif, et bloque
as anyet@ts-ignoreen CI (ESLint sait faire). - Fige tes versions et écris-les dans le fichier de contexte de ton agent (CLAUDE.md ou équivalent) : « Next 15, Prisma 6, Node 22 ». Le modèle improvise moins quand il sait sur quoi il travaille.
- Choisis des frameworks à conventions fortes pour tout nouveau projet : moins de décisions libres, c'est moins d'improvisation du modèle.
- Pour ton prochain service, fais un test réel : la même feature générée dans deux stacks candidates. Compare le nombre d'allers-retours avec l'agent, la facilité de relecture, et ton niveau de confiance dans le résultat.
- Ajoute une ligne à ta grille de choix de stack : « coût IA » (relisibilité, prévisibilité, verbosité, stabilité), à côté de « recrutement » et « écosystème ».
Le fond de l'affaire, c'est ça : ton langage est devenu une interface entre toi et le modèle. Choisis-la comme tu choisirais une API — lisible, prévisible, stable.