Blog Typescript

Typescript: « as » et excès de confiance...

Baptiste G. 3 min de lecture

Lorsqu’on lit ou écrit du code avec Typescript, on rencontre souvent le mot clé as. Sous son apparence anodine, il me parait important de ne pas ignorer ce qu’il implique. Petit tour d’horizon.

Qu’est-ce que c’est ?

On appelle ça une assertion de type (Type assertion). Cela signifie qu’il permet de préciser un type que Typescript lui-même n’est pas capable de déterminer. On indique au compilateur/transpilateur de Typescript quelque chose comme : “T’inquiète, je gère ! Je sais que cette data est de type XY, fais-moi confiance!”

Un chevalier en armure avec le texte "Typescript Code", puis la même image avec une flèche dans la tête et le texte "as any"

Ne pas reproduire chez soi

Voici comment on l’utilise:

const el = document.getElementById("app") as HTMLDivElement;

const data = JSON.parse(json) as User;

De fait, on désactive l’exécution du contrôle du type par le transpilateur. Ce qui rendra silencieuse toute erreur jusqu’au runtime. On a donc tout intérêt à savoir ce que l’on fait!

Règle de compatibilité

Typescript n’autorise le as que si le type source (string) est assignable au type cible (number).

const x = "hello" as number;
/* 
    ❌ Error: Conversion of type "string"
    to type "number" may be a mistake 
    because neither type sufficiently overlaps with the other.
*/

Le hack

Sachez qu’il existe un moyen de forcer une assignation rejetée par le transpilateur. C’est un signal d’alerte car cela contourne totalement la sécurité des types. Il faut encore plus redoubler de précaution dans ce cas.

const x = "hello" as unknown as number; // ✅ compile, mais dangereux
// ou
const x = "hello" as any as number; // ✅ compile, mais dangereux

Sans vouloir lancer un débat sur les tests de méthodes privées (avec le mot clé private, pas le signe JS natif #), c’est un moyen d’y accéder depuis un fichier de test 😉

Exemple : admettons que l’on teste un service MyService.

// Le service
export class MyService {
  private generateUUId(): string {
    return crypto.randomUUID();
  }
}

// Dans les tests .spec
...
it('should return a UUID', () => {
    const wrongResult = service.generateUUId();
    // ❌ Property 'generateUUId' is private
    // and only accessible within class 'MyService'.

    const result = (service as any).generateUUId();
    // ✅ Ça fonctionne! (mais c'est mal 😣)

    ...
});

as const

On sort de l’assertion classique ici. Ça rend une valeur littérale et readonly :

const point = { x: 1, y: 2 };
// type: { x: number; y: number }

const point2 = { x: 1, y: 2 } as const;
// type: { readonly x: 1; readonly y: 2 }

const dirs = ["up", "down"] as const;
// type: readonly ["up", "down"] au lieu de string[]

Ça peut être utile pour les tuples, les unions de littéraux, et les objets de config qu’on veut figer.

exemple pour les unions de littéraux :

function handle(s: "success" | "error" | "pending") { ... }

const result1 = "success";

handhle(result);
// ❌ Error: string n'est pas assignable à "success" | "error" | "pending"

const result2 = "success" as const;
// type inféré : "success" (le littéral exact, pas string)

handle(status); // ✅ OK

satisfies (TS 4.9+) — souvent préférable

as change le type perçu. satisfies vérifie sans changer le type inféré :

type Config = Record<string, number | string>;

const config = {
  retries: 3,
  timeout: "30s",
} satisfies Config;
// config.retries est inféré comme `number` (littéral précis conservé)
// TS vérifie que la forme respecte Config, sans élargir le type

Avec as Config, on perdrait la précision de retries: number → on aurait juste number | string.

En résumé : as est un échappatoire de compilation, pas une garantie de sécurité. Utile localement (DOM, narrowing manuel), mais chaque as est une dette de confiance envers le transpilateur — à limiter et à justifier. On devrait y préférer un type checking rigoureux.

Typescript Syntaxe code débutant

Contact

Et votre prochaine mission ?