Vol. 4 · № 03 · Un atelier TypeScriptA TypeScript workshop

as & les assertions, ou tais-toi, je sais mieux as & assertions, or be quiet, I know better

Venant de Java/C#, on lit as comme un cast. Faux : il ne convertit rien, ne vérifie rien, ne touche pas la valeur. Il change juste ce que le compilateur croit — un contrat qu'on signe à sa place. Légitime quand on détient un fait qu'il ne peut pas connaître ; mensonge quand on fait taire une erreur qu'on n'a pas comprise. Sur un JSON.parse, ce n'est qu'un any rebaptisé. Coming from Java/C#, you read as as a cast. Wrong: it converts nothing, checks nothing, doesn't touch the value. It only changes what the compiler believes — a contract you sign in its place. Legitimate when you hold a fact it can't know; a lie when you silence an error you didn't understand. On a JSON.parse, it's just a renamed any.

AudienceAudience
Dev qui dégaine as pour faire passer les types et le prend pour une conversion Dev who reaches for as to make the types pass and mistakes it for a conversion
Format
Self-paced
ChapitresChapters
5
Date
Juin 2026 Jun 2026
≈ 18 min ●●○○ Type assertionas constTradeoff
SommaireContents ·
№ 01CadrageFraming3 min

as n'est pas une conversion. C'est une signature : « tais-toi, je sais mieux. »as isn't a conversion. It's a signature: "be quiet, I know better."

Venant de Java ou C#, on lit as comme un cast : une opération qui vérifie ou convertit à l'exécution. En TypeScript, rien de tel. as ne touche pas la valeur et n'exécute aucun code — il change seulement ce que le compilateur croit. C'est un contrat qu'on signe à sa place : « cette valeur est un User, je m'en porte garant ». Si on a tort, le compilateur s'est tu pour rien, et le bug revient intact au runtime.Coming from Java or C#, you read as as a cast: an operation that checks or converts at runtime. In TypeScript, nothing of the sort. as doesn't touch the value and runs no code — it only changes what the compiler believes. It's a contract you sign in its place: 'this value is a User, I vouch for it'. If you're wrong, the compiler went quiet for nothing, and the bug returns intact at runtime.

as sur un JSON.parse — la promesse que personne n'a vérifiéeas on a JSON.parse — the promise nobody checked
const user = JSON.parse(raw) as User;   // ✗ ressemble à une conversion — n'en est pas
user.name.trim();                       // le compilateur est muet…
// 💥 si le JSON n'a pas de .name : crash. 'as' n'a RIEN vérifié, RIEN converti.
« Cast » ailleurs, « as » ici'Cast' elsewhere, 'as' here
Cast (Java / C#)Cast (Java / C#)
vérifie ou convertit à l'exécutionchecks or converts at runtime
se trompe → exception immédiatewrong → immediate exception
as (TypeScript)as (TypeScript)
ne vérifie rien, ne convertit rienchecks nothing, converts nothing
se trompe → bug silencieux, plus tardwrong → silent bug, later

Le cast d'un langage nominal fait quelque chose à l'exécution. Le as de TypeScript ne fait rien d'autre que faire taire le compilateur — et l'erreur, si erreur il y a, ressurgit là où on ne regarde plus.A nominal language's cast does something at runtime. TypeScript's as does nothing but silence the compiler — and the error, if any, resurfaces where you're no longer looking.

Un as légitime — un fait que le compilateur ne peut pas connaîtreA legitimate as — a fact the compiler cannot know
// Le DOM renvoie le type large HTMLElement | null. MOI, je sais que c'est un input :
const input = document.getElementById("email") as HTMLInputElement;
input.value;   // ✓ justifiable — je l'ai écrit dans le HTML, le compilateur ne le voit pas
// L'invariant que j'affirme, je peux l'énoncer. C'est ça, un 'as' légitime.
// (Il efface aussi le '| null' : si l'id quitte le HTML, c'est un crash — à assumer.)
Le réflexe du numéroThe issue's reflex

« Ce as est-il une preuve que le compilateur ne peut pas faire seul — et que je peux, moi, justifier — ou l'aveu que je n'ai pas compris l'erreur ? » Si tu peux énoncer l'invariant en une phrase vraie, c'est une assertion. Sinon, c'est un vœu."Is this as a proof the compiler can't make on its own — one I can justify — or an admission I didn't understand the error?" If you can state the invariant in one true sentence, it's an assertion. Otherwise, it's a wish.

Pourquoi ce numéro clôt le Vol 4.Why this issue closes Vol 4.

Trois échappatoires, trois rapports à la vérification. any la débranche en silence. unknown l'exige avant tout usage. as la court-circuite par une signature : ni off, ni preuve, mais ta parole donnée au compilateur. C'est le dernier recours du volume — et celui sur lequel reposait déjà, sans le dire, le brand du Vol 3.Three escape hatches, three relationships to checking. any unplugs it silently. unknown demands it before any use. as short-circuits it with a signature: neither off nor proof, but your word given to the compiler. It's the volume's last resort — and the one Vol 3's brand already silently rested on.

№ 02La surpriseThe surprise4 min

as renomme le type, jamais la valeur. À l'exécution, il n'a jamais existé.as renames the type, never the value. At runtime, it never existed.

La preuve que as ne convertit rien : forçons un string en number par une double assertion. Le compilateur nous croit et raisonne sur un number. Mais à l'exécution, la valeur est restée le string "3" — alors n + 1 fait une concaténation et produit "31", sans la moindre erreur. as s'est effacé, comme tout type (Vol 2). Une vraie conversion, elle, est du code qui s'exécute et change réellement la valeur.The proof that as converts nothing: let's force a string into a number with a double assertion. The compiler believes us and reasons about a number. But at runtime, the value stayed the string "3" — so n + 1 does a concatenation and yields "31", without a single error. as erased itself, like every type (Vol 2). A real conversion, by contrast, is code that runs and actually changes the value.

La double assertion ment, et JavaScript s'en ficheThe double assertion lies, and JavaScript doesn't care
const n = "3" as unknown as number;   // le compilateur croit : number
const r = n + 1;                       // il croit : 4
console.log(r);                        // 💥 "31" — JS a fait une concaténation
console.log(typeof n);                 // "string" — la valeur n'a JAMAIS changé

Le as unknown as number a convaincu le compilateur, pas le moteur JavaScript. La valeur est restée un string ; seul son type a menti, le temps de la compilation. À l'exécution il ne reste que la valeur nue — et un + qui concatène. L'assertion n'a rien produit qu'un faux espoir.The as unknown as number convinced the compiler, not the JavaScript engine. The value stayed a string; only its type lied, for the duration of compilation. At runtime only the bare value remains — and a + that concatenates. The assertion produced nothing but false hope.

Une conversion fabrique une nouvelle valeur. Un as ne fabrique rien — il change l'étiquette, pas la chose, puis s'efface.A conversion builds a new value. An as builds nothing — it changes the label, not the thing, then erases.
№ 03La mécaniqueThe mechanics5 min

Une famille d'assertions — dont une seule ne ment jamais.A family of assertions — only one of which never lies.

as T affirme un type. x! est le as du null : « pas null, pas undefined ». as unknown as T force deux types sans recouvrement — l'aveu le plus bruyant. Et puis il y a as const, le seul honnête : il ne ment pas, il demande au compilateur d'inférer plus précisément (littéraux, readonly). TypeScript pose d'ailleurs un garde-fou : il refuse un as entre deux types qui ne se recouvrent pas — c'est pourquoi il faut passer par unknown pour mentir tout à fait.as T asserts a type. x! is the as of null: 'not null, not undefined'. as unknown as T forces two non-overlapping types — the loudest admission. And then there's as const, the only honest one: it doesn't lie, it asks the compiler to infer more precisely (literals, readonly). TypeScript even sets a guardrail: it refuses an as between two non-overlapping types — which is why you must go through unknown to lie outright.

La famille — quatre gestes, un seul sans risqueThe family — four gestures, only one without risk
const el = ref.current as HTMLInputElement;   // as T : « c'est un input »
const x  = maybe!;                            // x! : « ce n'est pas null/undefined »
const cfg = { mode: "dark" } as const;        // as const : fige en littéral readonly
const n  = "3" as unknown as number;          // as unknown as : forcer l'incompatible
Le garde-fou — TS refuse le saut entre types disjointsThe guardrail — TS refuses the leap between disjoint types
const n = "3" as number;   // ✗ Conversion of type 'string' to 'number' may be
                           //   a mistake... — TS refuse le saut direct
// Pour passer outre, il FAUT élargir d'abord : "3" as unknown as number.
// Cette obligation est un signal : tu sors des types qui se recouvrent.
Qui ment, qui ne ment pas ?Who lies, who doesn't?
Peut mentirCan lie
as Taffirme un type, non vérifiéasserts a type, unchecked
x!affirme non-null, non vérifiéasserts non-null, unchecked
as unknown as Tforce l'incompatible — alarmeforces the incompatible — alarm
Ne ment pasDoesn't lie
as constnarrowe vers le littéralnarrows to the literal
EffetEffectreadonly + type le plus précisreadonly + most precise type
RisqueRiskaucun : c'est une instruction, pas une parolenone: an instruction, not a claim
Les voisins, seulement nommés.The neighbors, only named.

Là où l'on dégaine un as pour « vérifier sans élargir », le bon outil est souvent satisfies — il contrôle la conformité sans écraser le type inféré (Vol 7). Le ! n'est qu'un as ciblé sur null/undefined : préfère un vrai test ou ?. quand tu peux. Et as const brille avec les unions discriminées (Vol 3) : il fige le discriminant en littéral plutôt que de l'élargir en string.Where you reach for an as to "check without widening", the right tool is often satisfies — it checks conformance without crushing the inferred type (Vol 7). The ! is just an as aimed at null/undefined: prefer a real test or ?. when you can. And as const shines with discriminated unions (Vol 3): it freezes the discriminant into a literal instead of widening it to string.

№ 04Le piègeThe trap4 min

Le as sur une donnée du dehors : un any qu'on a juste rebaptisé.The as on outside data: an any you merely renamed.

C'est le contre-exemple obligatoire du volume. fetch().json() renvoie any ; on pose as ApiResponse pour faire passer les types, et le code compile, vert, rassurant. Mais on n'a rien vérifié : on a pris le trou d'any et on lui a collé une étiquette de type. Le premier champ manquant rétablit le crash, à des écrans de distance de la cause. Ce qu'il fallait faire, c'est valider la donnée là où elle entre.This is the volume's mandatory counter-example. fetch().json() returns any; you slap on as ApiResponse to make the types pass, and the code compiles, green, reassuring. But you checked nothing: you took any's hole and stuck a type label on it. The first missing field restores the crash, screens away from the cause. What you needed to do was validate the data where it enters.

L'interface + as : une garantie qui n'existe pasThe interface + as: a guarantee that doesn't exist
interface ApiResponse { items: Item[] }

const res = await fetch("/api/items");
const data = await res.json() as ApiResponse;   // ✗ zéro vérification

data.items.map(renderItem);   // 💥 si la réponse n'a pas 'items' : crash
// Le 'as' a rebaptisé un any (le retour de .json()) en mensonge typé.

L'interface décrit un espoir ; le as ordonne au compilateur d'y croire. Aucune ligne ne regarde la donnée reçue. On a transformé un any honnêtement dangereux en un type faussement sûr — le pire des deux, parce qu'il inspire confiance.The interface describes a hope; the as orders the compiler to believe it. No line looks at the received data. You turned an honestly dangerous any into a falsely safe type — the worst of both, because it inspires confidence.

Les trois conditions d'un as honnête.The three conditions of an honest as.

Avant d'écrire un as, exige les trois : (1) tu détiens une information que le compilateur ne peut pas avoir (le DOM, une valeur que tu viens de valider, un littéral figé) ; (2) tu peux énoncer l'invariant en une phrase vraie ; (3) il est confiné et relisable — comme le as du smart constructor branded (3.3), un seul endroit qu'on garde à l'œil. Si l'une manque, ce n'est pas une assertion, c'est un vœu.Before writing an as, demand all three: (1) you hold information the compiler cannot have (the DOM, a value you just validated, a frozen literal); (2) you can state the invariant in one true sentence; (3) it's confined and reviewable — like the branded smart constructor's as (3.3), a single spot you keep an eye on. If one is missing, it's not an assertion, it's a wish.

Mettre as sur une donnée non vérifiée, ce n'est pas la typer — c'est promettre à sa place. La frontière ne se traverse pas par une parole : elle se valide.Putting as on unchecked data isn't typing it — it's promising on its behalf. The boundary isn't crossed by a claim: it's validated.
№ 05Bilan & éditoWrap-up & editorial2 min

Une parole donnée au compilateur — dont tu réponds, seul.A word given to the compiler — that you alone answer for.

as ne convertit rien et ne vérifie rien : il renomme le type, pas la valeur, puis s'efface. C'est un contrat qu'on signe à la place du compilateur — légitime quand on détient un fait qu'il ne peut pas connaître et qu'on sait justifier, mensonge dès qu'on l'emploie pour faire taire une erreur qu'on n'a pas comprise. Sur une donnée du dehors, ce n'est qu'un any rebaptisé : la frontière se valide, elle ne s'affirme pas.as converts nothing and checks nothing: it renames the type, not the value, then erases. It's a contract you sign in the compiler's place — legitimate when you hold a fact it can't know and can justify, a lie the moment you use it to silence an error you didn't understand. On outside data, it's just a renamed any: the boundary is validated, not asserted.

Tu veux…You want to…Le gesteThe moveCe que ça coûteWhat it costs
Affirmer un type que TS ne déduit pasAssert a type TS can't inferas T — un contrat que tu signes.as T — a contract you sign.Si tu as tort, le bug revient intact au runtime.If you're wrong, the bug returns intact at runtime.
Affirmer non-nullAssert non-nullx! — le as du null/undefined.x! — the as of null/undefined.Même risque : ne le pose que si tu peux le justifier.Same risk: only use it if you can justify it.
Figer un littéral (l'honnête)Freeze a literal (the honest one)as const — narrowe, ne ment pas.as const — narrows, doesn't lie.readonly : la valeur n'est plus mutable.readonly: the value is no longer mutable.
Ne PAS l'employerNOT use itas User sur un JSON.parse « pour que ça passe ».as User on a JSON.parse "to make it pass".Un any rebaptisé — valide à la frontière (Vol 7).A renamed any — validate at the boundary (Vol 7).
Un as justifiable est une preuve que tu fais à la place du compilateur. Un as commode est un mensonge que tu lui fais avaler — et c'est toi qui le paieras.A justifiable as is a proof you make in the compiler's place. A convenient as is a lie you feed it — and you're the one who'll pay.
Mot de l'éditeurFrom the editor

« Tais-toi, je sais mieux. »"Be quiet, I know better."

as est le seul endroit où l'on parle plus fort que le compilateur. Parfois on a raison : on tient une information qu'il ne peut pas avoir — la forme d'un élément du DOM, une valeur qu'on vient de valider, un littéral qu'on fige. L'assertion est alors une preuve qu'on fait à sa place, et qu'on saurait défendre. Mais le même mot, posé sur une erreur qu'on n'a pas lue, devient un mensonge confortable : le rouge disparaît, la responsabilité bascule sur nous, et si l'on s'est trompé, le bug revient exactement là où il était, à l'exécution, intact. La différence n'est pas dans la syntaxe — elle est dans la question qu'on s'est posée avant d'écrire les deux lettres.as is the one place where you speak louder than the compiler. Sometimes you're right: you hold information it can't have — the shape of a DOM element, a value you just validated, a literal you freeze. The assertion is then a proof you make in its place, one you could defend. But the same word, laid on an error you didn't read, becomes a comfortable lie: the red vanishes, the responsibility shifts onto you, and if you were wrong, the bug returns exactly where it was, at runtime, intact. The difference isn't in the syntax — it's in the question you asked yourself before typing the two letters.

Ainsi se ferme le Vol 4. any débranche la vérification en silence, unknown l'exige avant tout usage, as la court-circuite par une signature. Trois façons d'abandonner la preuve — et le réflexe commun : savoir exactement où elle s'arrête. Le prochain volume prend le chemin inverse. Au lieu de renoncer au type, les génériques le relient : un code qui marche pour toute une famille de types sans rien abandonner de la vérification. On passe de « j'ignore ce type » à « je le garde, et je le fais voyager ».So Vol 4 closes. any unplugs checking silently, unknown demands it before any use, as short-circuits it with a signature. Three ways to abandon the proof — and the shared reflex: know exactly where it stops. The next volume takes the opposite path. Instead of giving up the type, generics relate it: code that works for a whole family of types without abandoning any checking. We move from 'I don't know this type' to 'I keep it, and I carry it across'.