Elm Language Amélioration de la sécurité des types en utilisant de nouveaux types


Exemple

Les types d'alias réduisent les problèmes et améliorent la lisibilité, mais ce n'est pas plus sûr que le type alias lui-même. Considérer ce qui suit:

type alias Email = String

type alias Name = String

someEmail = "holmes@private.com"

someName = "Benedict"

sendEmail : Email -> Cmd msg
sendEmail email = ...

En utilisant le code ci-dessus, nous pouvons écrire sendEmail someName , et il compilera, même si cela ne devrait vraiment pas être le cas, car malgré les noms et les emails étant tous deux des String , ils sont complètement différents.

Nous pouvons vraiment distinguer une String d'une autre String au niveau du type en créant un nouveau type . Voici un exemple qui réécrit Email comme un type plutôt qu'un type alias :

module Email exposing (Email, create, send)

type Email = EmailAddress String

isValid : String -> Bool
isValid email = 
  -- ...validation logic

create : String -> Maybe Email
create email =
    if isValid email then
        Just (EmailAddress email)
    else
        Nothing

send : Email -> Cmd msg
send (EmailAddress email) = ...

Notre fonction isValid fait quelque chose pour déterminer si une chaîne est une adresse électronique valide. La fonction create vérifie si une String donnée est un email valide, renvoyant un Email Maybe -wrapped pour s'assurer que nous ne renvoyons que des adresses validées. Bien que nous puissions contourner le contrôle de validation en construisant un Email directement en écrivant EmailAddress "somestring" , si notre déclaration de module n'expose pas le constructeur EmailAddress , comme indiqué ici

module Email exposing (Email, create, send)

alors aucun autre module n'aura accès au constructeur EmailAddress , bien qu'ils puissent toujours utiliser le type Email dans les annotations. La seule façon de créer un nouvel Email dehors de ce module consiste à utiliser la fonction create qu'elle fournit et cette fonction garantit qu'elle ne renverra que des adresses e-mail valides. Par conséquent, cette API guide automatiquement l'utilisateur sur le chemin correct via son type de sécurité: send ne fonctionne qu'avec les valeurs construites par create , qui effectue une validation et applique le traitement des emails non valides car il retourne un Maybe Email - Maybe Email .

Si vous souhaitez exporter le constructeur Email , vous pouvez écrire

module Email exposing (Email(EmailAddress), create, send)

Désormais, tout fichier importé Email peut également importer son constructeur. Dans ce cas, cela permettrait aux utilisateurs de contourner la validation et d' send des e-mails non valides, mais vous ne construisez pas toujours une API comme celle-ci, donc les constructeurs exportateurs peuvent être utiles. Avec un type qui a plusieurs constructeurs, vous pouvez également ne vouloir exporter que certains d'entre eux.