Koska konekirjoitus on kasvamassa ja saamassa suosiota viime aikoina, yhä useammat JavaScript-kehittäjät arvostavat kirjoitusturvallisuutta. Typescriptin tarjoamien ominaisuuksien luettelo on valtava ja saattaa olla ylivoimainen, joten tässä viestissä keskityn yhteen niistä, joka on helppo käsittää ja jolla on siisti käytännön vaikutus.
Aloitetaan esimerkillä. Kuvittele, että kehität sovellusta, jolla on useita käyttäjärooleja. On melko yleistä, että eri käyttäjät käyttävät sovellusta, eikö niin? Tarkat roolit eivät ole tärkeitä, mutta oletetaan, että ne ovat admin
, consumer
ja guest
. Konekirjoituksessa voimme ilmoittaa käyttäjät, joilla on kyseiset roolit, seuraavasti:
type Admin = {} type Consumer = {} type Guest = {}
Tarkastellaan nyt joukko attribuutteja, jotka kullakin käyttäjäroolilla on. Yleensä ne ovat email
, firstName
ja lastName
tai jotain vastaavaa. Mutta odota, Guest
ei todennäköisesti ole niitä (hehän ovat vieraita), joten jätetään tämä tyyppi toistaiseksi tyhjäksi.
type Admin = { firstName: string lastName: string email: string } type Consumer = { firstName: string lastName: string email: string } type Guest = {}
Sovelluksen käyttäjällä voi olla vain yksi rooli. Tapa esittää tämä tyyppien kautta on käyttää union
.
type User = Admin | Consumer | Guest
Järjestelmänvalvojat ovat kuuluisia ainutlaatuisista kyvyistään, ja sovelluksessamme he voivat kutsua kuluttajia. Lisätään kenttä, joka kertoo kuinka monta kutsua järjestelmänvalvoja voi lähettää.
type Admin = { firstName: string lastName: string email: string numberOfInvitesLeft: number // <-- added }
Jotta asiat olisivat mielenkiintoisempia ja lähempänä todellista sovellusta, lisätään Consumer
yksinoikeudellinen omaisuus.
type Consumer = { firstName: string lastName: string email: string premium: boolean // <-- added }
Tämä on hyvin yksinkertainen esimerkki, ja todellisuudessa käyttäjillä voi olla kymmeniä erilaisia ominaisuuksia, mikä monimutkaistaa huomattavasti koodikantaa, kun sinun on käytettävä tiettyjä ominaisuuksia.
const doSomethingBasedOnRole = (user: User) => { // how do you check here that user is really an admin if (user) { // ...and do something with the `numberOfInvitesLeft` property? } }
Yksi vaihtoehto on tarkistaa kiinteistön olemassaolo.
const doSomethingBasedOnRole = (user: User) => { if (user && user.numberOfInvitesLeft) { // safely access `numberOfInvitesLeft` property } }
Mutta tämä on työläs eikä skaalautuva ratkaisu. Ja mitä tehdä, kun "numberOfInvitesLeft" muuttuu valinnaiseksi omaisuudeksi?
Tässä tulee esiin syrjityt ammattiliittotyypit. Meidän on vain lisättävä jokaiseen käyttäjätyyppiin lisäkenttä, joka ilmaisee roolin.
type Admin = { firstName: string lastName: string email: string numberOfInvitesLeft: number role: "admin" // <-- added } type Consumer = { firstName: string lastName: string email: string role: "consumer" // <-- added } type Guest = { role: "guest" // <-- added }
Huomaa, kuinka laitan tietyn merkkijonon tyypiksi; tätä kutsutaan merkkijono-literaalityypiksi . Tämä antaa sinulle sen, että nyt voit käyttää JS-kielen natiivioperaattoreita, esim. switch case
, if
, else
roolin erotteluun .
const user: Admin = { firstName: "John", lastName: "Smith", email: "[email protected]", numberOfInvitesLeft: 3, role: "admin", } const doSomethingBasedOnRole = (user: User) => { if (user.role === "admin") { // now typescript knows that INSIDE of this block user is of type `Admin` // now you can safely call `user.numberOfInvitesLeft` within this block } }
Sama koskee kytkimen tapausta.
// ... const doSomethingBasedOnRole = (user: User) => { switch (user.role) { case "admin": { // now typescript knows that INSIDE of this block user is of type `Admin` // now you can safely call `user.numberOfInvitesLeft` within this block } case "consumer": { // do something with a `Consumer` user // if you try to call `user.numberOfInvitesLeft` here, TS compiler errors in // // "Property 'numberOfInvitesLeft' does not exist on type 'Consumer'." // } } }
Syrjittyjen liittotyyppien edut ovat ilmeisiä, koska tyyppitarkistus perustuu nimenomaiseen rooliominaisuuteen eikä ad-hoc-ominaisuuksiin, jotka saattavat liittyä tai eivät liity tiettyyn käyttäjään.