تایپ اسکریپت یک superset جاوااسکریپت است که ویژگیهای بیشماری را برای کمک به توسعهدهندگان برای نوشتن کد ایمن و مستندسازی بهتر آنها معرفی میکند. یکی از این ویژگیها type predicate است. در این مقاله قصد داریم تا با مفهوم type predicate در تایپ اسکریپت آشنا شویم، بررسی کنیم که این ویژگی چرا مفید است و چگونه باید از آن در پروژههای خود استفاده کنیم.
یک type predicate تابعی است که تایپ بازگشتی آن یک مقدار بولین میباشد، که برای محدود کردن تایپها مورد استفاده قرار میگیرد. زمانی که تایپ اسکریپت نمیتواند به طور خودکار تایپ یک متغیر را استنتاج کند، یا زمانی که بررسیهای تایپ پیچیدهتری مورد نیاز است، استفاده از type predicate میتواند مفید باشد.
سینتکس تابع type predicate به شکل زیر میباشد:
function isOfType(arg: any): arg is Type { // ... logic }
arg is Type
سینتکس type predicate است. این کد به تایپ اسکریپت سیگنال میدهد که وقتی تابع مقدار true
را return میکند، فراخوانی کننده تابع میتواند مطمئن شود که arg
از نوع Type
است.
سناریویی را در نظر میگیریم که در آن یک union type (به عنوان مثال، string | number
) داریم و میخواهیم کدهای مختلفی را بر اساس تایپ اجرا کنیم. روش استاندارد، استفاده از type guardها میباشد:
function processInput(input: string | number) { if (typeof input === 'string') { console.log(input.toUpperCase()); } else { console.log(input.toFixed(2)); } }
در حالی که typeof
و instanceof
هر دو مفید هستند، اما همه موارد را پوشش نمیدهند. اینجاست که type predicateها مطرح میشوند. آنها به توسعهدهندگان اجازه میدهند تا type guardهای سفارشی ایجاد کنند که تایپها را بر اساس منطق سفارشی محدود میکند.
فرض کنید دو interface Cat
و Dog
داریم و میخواهیم بررسی کنیم که آیا یک حیوان Cat
است یا خیر:
interface Cat { purr(): void; } interface Dog { bark(): void; } function isCat(animal: Cat | Dog): animal is Cat { return (animal as Cat).purr !== undefined; }
اکنون، هر زمان که از isCat
در یک حالت شرطی استفاده میکنیم، تایپ اسکریپت تایپ آن را میداند:
const myPet: Cat | Dog = getPetSomehow(); if (isCat(myPet)) { myPet.purr(); // TypeScript knows `myPet` is a `Cat` here. } else { myPet.bark(); }
به طور مشابه میتوانیم از type predicate به همراه کلاس استفاده کنیم:
class Bird { fly() { /*...*/ } } class Fish { swim() { /*...*/ } } function isBird(pet: Bird | Fish): pet is Bird { return (pet as Bird).fly !== undefined; }
مواردی که هنگام استفاده از type predicateها حتما باید به آنها توجه داشته باشته باشیم عبارتند از:
true
را return میکند، تایپ اسکریپت کاملاً به این مقدار اطمینان دارد، بنابراین این مقدار دوباره بررسی نمیشود. در نتیجه باید مطمئن شویم که predicateهای ما حتما درست باشند.arg is Type
است.typeof
و instanceof
کافی نیستند، بسیار مفید میباشد.