Тъй като typescript расте и набира популярност напоследък, все повече разработчици на javascript оценяват безопасността на типа. Списъкът с функции, предоставяни от Typescript, е огромен и може да е огромен, така че в тази публикация ще се съсредоточа върху една от тях, която е лесна за разбиране и има чудесно практическо въздействие.
Да започнем с един пример. Представете си, че разработвате приложение с много потребителски роли. Доста обичайно е едно приложение да се използва от различни потребители, нали? Точните роли не са особено важни тук, но да кажем, че те са admin
, consumer
и guest
. В typescript можем да декларираме потребители, притежаващи тези роли, както следва:
type Admin = {} type Consumer = {} type Guest = {}
Сега нека разгледаме набор от атрибути, които има всяка потребителска роля. Обикновено те са email
, firstName
и lastName
или нещо подобно. Но изчакайте, потребителите Guest
вероятно няма да имат такива (все пак са гости), така че нека просто оставим този тип празен за сега.
type Admin = { firstName: string lastName: string email: string } type Consumer = { firstName: string lastName: string email: string } type Guest = {}
Потребителят на приложение може да има само една роля. Начинът да се представи това чрез типове е да се използва тип union
.
type User = Admin | Consumer | Guest
Администраторите са известни със своите изключителни способности и в нашето приложение те могат да канят потребители. Нека добавим поле, показващо колко покани може да изпрати администратор.
type Admin = { firstName: string lastName: string email: string numberOfInvitesLeft: number // <-- added }
За да направим нещата по-интересни и по-близки до реално приложение, нека добавим свойство, изключително за тип Consumer
.
type Consumer = { firstName: string lastName: string email: string premium: boolean // <-- added }
Това е много прост пример и в действителност потребителите могат да имат десетки различни свойства, което значително усложнява кодовата база, когато имате нужда от достъп до определени свойства.
const doSomethingBasedOnRole = (user: User) => { // how do you check here that user is really an admin if (user) { // ...and do something with the `numberOfInvitesLeft` property? } }
Единият вариант е да проверите съществуването на имота.
const doSomethingBasedOnRole = (user: User) => { if (user && user.numberOfInvitesLeft) { // safely access `numberOfInvitesLeft` property } }
Но това е досадно и не мащабируемо решение. И какво да направите, когато `numberOfInvitesLeft` стане незадължително свойство?
Това е мястото, където дискриминираните синдикални типове влизат в действие. Просто трябва да поставим допълнително поле във всеки тип потребител, указващо ролята.
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 }
Забележете как поставям конкретен низ като тип; това се нарича тип низов литерал . Това, което ви дава, е, че сега можете да използвате оператори на родния JS език, напр. switch case
, if
, else
за да разграничите ролята.
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 } }
Същото важи и за оператор за превключване на случай.
// ... 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'." // } } }
Ползите от дискриминираните типове обединения са очевидни, тъй като проверката на типа се основава на изрично свойство на ролята, а не на ad-hoc свойства, които могат или не могат да бъдат свързани с конкретен потребител.