Annotation TypeScript "as const"

L’annotation TypeScript "as const" permet d’indiquer qu’une valeur est profondément en lecture seule et immuable. Son effet diffère de celui de "Object.freeze", car elle n’agit qu’à la compilation, tandis que Object.freeze ne s’applique qu’au premier niveau de l’objet gelé.

Dans cet article, je souhaite présenter quelques exemples utiles de l’annotation "as const".

Les valeurs marquées "as const" ne peuvent pas être modifiées

const warrior = {
  weapons: {
    sword: true,
    knife: false,
  },
} as const;

warrior.weapons.sword = false;
//      ☝️ Erreur : impossible d’affecter une valeur à "weapons", car cette propriété est en lecture seule.

Cela fonctionne aussi avec les tableaux :

const array = ["a", "b", "c"] as const;
array.push("d");
//  ☝️ Erreur : la propriété 'push' n’existe pas sur le type 'readonly ["a", "b", "c"]'

Peut remplacer le mot-clé "enum"

Enum n’existe pas en JavaScript : l’équipe TypeScript l’a créé pour permettre aux développeurs de définir un ensemble de constantes nommées. Cela peut parfois être pratique, mais présente aussi quelques inconvénients. L’un d’eux est un système de typage assez rigide.

Prenons cet exemple :

enum Roles {
    ADMIN = "admin",
    MANAGER = "manager",
    VISITOR = "visitor",
}

function isAdmin(role: Roles) {
  return role === Roles.ADMIN;
}

isAdmin(Roles.ADMIN); // ✅Valide, mais il fallait importer Roles pour l’utiliser
isAdmin("admin"); // ❌Erreur : l’argument de type '"admin"' n’est pas assignable au paramètre de type 'Roles'

On voit clairement qu’il est impossible d’utiliser directement "admin", même si cette valeur est identique à Roles.ADMIN.

Pour éviter cela, nous pouvons utiliser "as const" :

const ROLES = {
  ADMIN: "admin",
  MANAGER: "manager",
  VISITOR: "visitor",
} as const;

// On peut ensuite définir un type pour obtenir l’union de toutes les valeurs possibles de ROLES
type Role = typeof ROLES[keyof typeof ROLES];

function isAdmin(role: Role) {
  return role === ROLES.ADMIN; // Ou role === "admin"
}

isAdmin(ROLES.ADMIN);
//  ✅ Valide
isAdmin("admin");
// ✅ Valide aussi, sans avoir besoin d’importer quoi que ce soit

Conclusion

"As const" en TypeScript est un outil précieux pour créer des types littéraux immuables, avec des inférences de types plus précises et une meilleure sûreté de typage. Cette assertion permet de conserver les valeurs littérales spécifiques des variables et des propriétés, d’éviter les modifications accidentelles et de détecter plus tôt d’éventuels bugs. L’intégrer à votre codebase TypeScript peut contribuer à créer des applications plus robustes et plus fiables.

Pour aller plus loin :

  • https://blog.logrocket.com/complete-guide-const-assertions-typescript/
  • https://www.totaltypescript.com/concepts/as-const