تایپ اسکریپت چیست؟ چرا باید تایپ اسکریپت یاد بگیریم؟

تایپ اسکریپت چیست؟ چرا باید تایپ اسکریپت یاد بگیریم؟

سلام به همه همراهان سکان آکادمی،

امروز می‌خواهیم درباره "تایپ‌اسکریپت" (TypeScript) صحبت کنیم و بعضی از مطالب مربوط به این زبان را با هم یاد بگیریم. چون واقعیت این است که خود من هم تازه دارم با این زبان آشنا می‌شوم.

در این مقاله، "انواع داده‌ها (data types)" و اینکه "چرا باید تایپ‌اسکریپت یاد بگیریم؟" را با هم آموزش می‌بینیم.

تایپ‌اسکریپت (TypeScript) چیست؟

همانطور که می‌دانید، جاوا‌اسکریپت (JavaScript)، یکی از محبوب‌ترین زبان‌های برنامه‌نویسی حال حاضر دنیاست. یکی از دلایلش می‌تواند این باشد که نسبت به دیگر زبان‌ها، در نحوه نوشتن (syntax)، محدودیت و سخت‌گیری ندارد.

به عبارت دیگر، جاوا‌اسکریپت زبان آزاد و بدون محدودیتی است، اما هنگامی که حجم کدها در پروژه‌ی شما زیاد شود، این آزادی، به درد و سختی تبدیل می‌شود. به طور مثال به این قطعه کد نگاه کنید:

// Can you guess the return value?
const variable = (a, b) => {
  return a + b;
}

آیا می‌توانید مقدار خروجی این قطعه کد را حدس بزنید؟

من که نمی‌توانم!

واقعا در جاوا‌اسکریپت نمی‌توان خروجی این کد را حدس زد. زیرا این تابع می‌تواند هر مقداری از انواع مختلف داده را دریافت کند. رشته (String)، عدد (Number) و غیره.

1. اگر مقادیر ورودی عدد باشند:

// Arguments is number.
const variable = (a, b) => {
    return a + b;
  }
  const result = variable(2021, 9);
  console.log(result); // 2030

2. اگر مقادیر ورودی رشته باشند:

  // Arguments is string.
const variable = (a, b) => {
    return a + b;
  }
  const result = variable("2021", "9");
  console.log(result); // 20219

جاوا اسکریپت زبانی پویا برای انواع داده‌هاست و این ویژگی نوشتن کدها را ساده‌تر می‌کند. اما توسعه دهنده‌های این زبان، باید دقت بیشتری روی مقادیر ورودی داشته باشند و بدانند چه مقادیری می‌توانند به عنوان ورودی این تابع در نظر گرفته شوند. همچنین چه نوع داده‌ای به عنوان خروجی این تابع به وجود می‌آید.

هر چه بیشتر و بیشتر با جاوا اسکریپت کد بزنیم، بیشتر متوجه خواهیم شد که این ویژگی استرس‌زا و ریسکی است.

حالا به این قطعه کد نگاه کنید:

// Can you guess the return value?
const variable = (a: number, b: number): number => {
   return a + b;
}

اکنون می‌توانید حدس بزنید این تابع چه خروجی می‌تواند داشته باشد؟

اگر من هم چیزی نگویم کاملا مشخص است...

این قطعه کد با تایپ‌اسکریپت نوشته شده است. تایپ‌اسکریپت همانند جاوا‌اسکریپت پویا نیست و از یک ساختار ثابت و داده‌های مشخص استفاده می‌کند. در قطعه کد بالا کاملا مشخص است که این تابع تنها عدد قبول می‌کند و خروجی تابع هم حتما یک عدد است.

این نوع ساختار بسیار مفید و کاربردی است؛ زیرا در پروژه‌ها و شرکت‌های بزرگ، خواندن و فهمیدن کدهایی که در گذشته نوشته شده اند، بسیار سخت و پیچیده است.

انواع داده در تایپ‌اسکریپت به زبان ساده

تایپ‌اسکریپت، به صورت پیشفرض چندین نوع داده (data type) اولیه دارد. مثل رشته‌ها، اعداد، boolean، null، undefined و غیره.

در مثال زیر بخشی از data type های موجود در این زبان را با هم بررسی می‌کنیم:

// string, number and boolean.
const caterpie01: number = 2021;    // OK
const caterpie02: number = false;   // NG

const Metapod01: string = "sleepy"; // OK
const Metapod02: string = true;     // NG

const Wartortle01: boolean = true;  // OK
const Wartortle02: boolean = 1111;  // NG

با اجرای این قطعه کد، در console اخطارهای زیر را می‌بینیم:

typescript.ts:10:7 - error TS2322: Type 'boolean' is not assignable to type 'number'.

10 const caterpie02: number = false;   // NG
         ~~~~~~~~~~

typescript.ts:13:7 - error TS2322: Type 'boolean' is not assignable to type 'string'.

13 const Metapod02: string = true;     // NG
         ~~~~~~~~~

typescript.ts:16:7 - error TS2322: Type 'number' is not assignable to type 'boolean'.

16 const Wartortle02: boolean = 1111;  // NG
         ~~~~~~~~~~~

اما درباره مقادیر null و undefined چطور؟

// null and undefined.
const Butterfree: null = null;
const ButterfreeNull: string = Butterfree;
console.log(ButterfreeNull) // null

const Kakuna: undefined = undefined;
const KakunaNull: string = Kakuna;
console.log(KakunaNull) //undefined

این قطعه کد اجرا می‌شود و مشکلی ندارد. ما می‌توانیم به یک رشته (string) مقادیر null و undefined بدهیم.

اما نکته ای که باید به آن توجه کنیم این است که، هنوز حالت strict mode در تایپ‌اسکریپت را فعال نکردیم.

(Strict Mode در تایپ‌اسکریپت به این صورت عمل می‌کند که حساسیت بررسی "انواع داده‌ها" را بالا برده و ما نمی‌توانیم حتی مقادیر null و undefined را به یک نوع داده‌ی دیگر بدهیم.)

زمانی که حالت strict mode را true قرار دهیم، در هنگام اجرای کد به اخطار زیر بر می‌خوریم:

typescript.ts:21:7 - error TS2322: Type 'null' is not assignable to type 'string'.

21 const ButterfreeNull: string = Butterfree;
         ~~~~~~~~~~~~~~

typescript.ts:25:7 - error TS2322: Type 'undefined' is not assignable to type 'string'.

25 const KakunaNull: string = Kakuna;

حالت strict mode در تنظیمات خود تایپ اسکریپت و در فایل tsconfig.json یا همچنین توسط دستور strict— قابل تغییر و تنظیم است.

اگر تا به حال این تنظیمات را انجام نداده اید، از این لینک وارد وبسایت اصلی تایپ‌اسکریپت شده و شیوه انجام آن را مرور کنید.

نوع داده‌ی ANY در تایپ‌اسکریپت به چه معنا است؟

تایپ‌اسکریپت یک "نوع داده" به نام any دارد. این نوع، به ما اجازه می‌دهد که از همه نوع داده‌ها، بدون خطا استفاده کنیم. این نوع داده، شبیه چیزی است که در جاوا‌اسکریپت داریم.

به قطعه کد زیر نگاه کنید:

// any data type
let birthday: any = 1991;
console.log(typeof birthday) // number

birthday = "bird";
console.log(typeof birthday) // string

birthday = false;
console.log(typeof birthday) // boolean

birthday = null;
console.log(typeof birthday) // object

birthday = undefined;
console.log(typeof birthday) // undefined

متغیر "birthday" می‌تواند هر نوع داده‌ای داشته باشد.

به نوعی می‌توان گفت، زمانی که از نوع داده‌ی any استفاده می‌کنیم، اصلا از typescript استفاده نمی‌کنیم! بلکه در حال نوشتن همان کدهای جاوااسکریپت هستیم.

*این بدیهی است، زیرا همانطور که از اسم typescript پیداست، نوعی از اسکریپت نویسی است که تمرکز ویژه‌ای بر تایپ‌ها دارد.

حتی اگر هم مشخص نکنیم، تایپ‌اسکریپت می‌تواند نوع داده‌ها را تشخیص دهد.

مثال زیر را با هم ببینیم:

// typescript can guess data types.
const caterpie01: number = 2021;     // number   - we tell it
const caterpie001 = 2021;            // number   - typescript guess

const Metapod01: string = "sleepy";  // string   - we tell it
const Metapod001 = "sleepy";         // string   - typescript guess

const Wartortle01: boolean = true;   // boolean  - we tell it
const Wartortle001 = true;           // boolean  - typescript guess

یقینا این روش (که دیگر نیازی نیست ما نوع داده را مشخص کنیم و خود تایپ‌اسکریپت متوجه می‌شود) کوتاه‌تر است. همچنین در این روش هم ما نمی‌توانیم داده از نوع دیگری را به این متغیر بدهیم.

let caterpie001 = 2021;            // number
caterpie001 = "text";              // type error

اما از طرف دیگر، اگر ما در توابع، نوع داده‌های ورودی را مشخص نکنیم، تایپ‌اسکریپت نوع این داده‌ها را any در نظر می‌گیرد و ممکن است مشکل ساز شود.

مثال زیر را ببینیم:

const pikachu = (a, b): number => {
  return a + b;
}
pikachu(2021, 9);

در این مثال به این خطا بر می‌خوریم:

typescript.ts:57:18 - error TS7006: Parameter 'a' implicitly has an 'any' type.

57 const pikachu = (a, b): number => {
                    ~

typescript.ts:57:21 - error TS7006: Parameter 'b' implicitly has an 'any' type.

57 const pikachu = (a, b): number => {

*البته این نکته را نباید فراموش نکنیم که در این لحظه strict mode فعال و true است. اگر این حالت رو false قرار دهیم، کامپایل با موفقیت انجام شده و به ما خطایی نمی‌دهد.

دلیل این خطا این است که تایپ‌اسکریپت نمی‌تواند نوع مقادیر ورودی تابع را تشخیص دهد و این مقادیر ورودی می‌توانند هر نوع داده‌ای را شامل شوند. بنابراین زمانی که در تایپ‌اسکریپت از تابع استفاده می‌کنیم، حتما باید نوع داده را به صورت زیر مشخص کنیم:

const pikachu = (a: number, b: number): number => {
  return a + b;
}

توصیه می‌شود که از نوع داده any فقط در صورت لزوم استفاده کنیم. برای مثال زمانی که بعضی از کدها را از JavaScript به TypeScript انتقال می‌دهیم.

نوع داده‌ی Object در تایپ اسکریپت

تایپ‌اسکریپت نوع داده‌ی آبجکت را با استفاده از interface ایجاد می‌کند.

قبل از توضیح کامل، به مثال زیر نگاهی می‌اندازیم:

// define object data type with interface.
interface UserObj {
  name: string,
  age: number,
  skill: string
}
// assign data type to object.
const user: UserObj = {
  name: "pikachu",
  age: 6,
  skill: "Developer"
}

ما با استفاده از سینتکس interface می‌توانیم یک نوع داده‌ی آبجکت بسازیم و سپس آن را به یک آبجکت نسبت بدهیم.

همانطور که در مثال می‌بینیم، با تعریف یک interface، ساختار و نوع داده‌های آبجکت را مشخص می‌کنیم. سپس برای تعریف دیگر آبجکت‌ها از این ساختار استفاده می‌کنیم. اگر یکی از انواع داده‌های آن آبجکت را تغییر دهیم با خطا مواجه می‌شویم.

همانند مثال زیر:

// define object data type with interface.
interface UserObj{
  name: string,
  age: number,
  skill: string
}
// assign data type to object.
const user: UserObj = {
  name: "pikachu",
  age: "change age",       // change 
  skill: "Developer
}

خطا:

typescript.ts:75:3 - error TS2322: Type 'string' is not assignable to type 'number'.

75   age: "change age",
     ~~~

  typescript.ts:69:3
    69   age: number,
         ~~~
    The expected type comes from property 'age' which is declared here on type 'UserObj'

خیلی خوب است اگر نوع داده یک آبجکت را با استفاده از interface تعریف کنیم. اما این را هم باید بدانیم که به راحتی می‌توان data type یک Object را به صورت مستقیم و بدون استفاده از interface هم تعریف کرد.

// assign data type directly to object.
const user: {name: string, age: number, skill: string} = {
  name: "pikachu",
  age: 6,
  skill: "Developer"
}

نوع داده‌ی Array در تایپ اسکریپت

نحوه تعریف یک آرایه در تایپ‌اسکریپت به صورت زیر است:

// define array data type
const userName: string[] = ["pikachu", "Raichu", "Charizard"];

اما اگر در این مورد نوع داده‌ی این آرایه را تغییر بدیم... :

/ change array data type
const userName: string[] = ["pikachu", "Raichu", false];

با خطای زیر مواجه می‌شویم:

typescript.ts:80:49 - error TS2322: Type 'boolean' is not assignable to type 'string'.

80 const userName: string[] = ["pikachu", "Raichu", false];

این میزان سخت‌گیری و این نوع خطاها واقعا مفید هستند زیرا دیگر مجبور نیستیم انواع داده‌های تمامی المان‌های داخلی یک آرایه را تحت نظر داشته باشیم و خود تایپ‌اسکریپت حواسش به این موارد هست.

اکنون، روش دیگری از تعریف انواع داده در تایپ‌اسکریپت را با هم بررسی می‌کنیم. عملکرد این روش دقیقا همانند مثال بالا است. مثال زیر را با هم ببینیم:

// defined array with another way.
const userName: Array<string> = ["pikachu", "Raichu", "Charizard"];

نوع داده‌ی generics در تایپ اسکریپت چیست؟

Data type بعدی، نوع داده‌ی generics در تایپ‌اسکریپت است. همانطور که از اسم این نوع داده مشخص است، یک انواع داده‌ی عمومی است. 

حتما و یقینا بارها و بارها برای شما هم پیش آمده که هنگامی استفاده از یک متغیر، تازه نوع آن مشخص می‌شود. در اینجا نوع داده‌ی generics در تایپ‌اسکریپت به کمک ما می‌آید.

بعد از تعریف یک نوع داده‌ی عمومی، می‌توانیم نوع دقیق آن را مشخص کنیم و سپس از آن استفاده کنیم. (به عبارت دیگر، نوع دقیق یک متغیر را در هنگام استفاده از آن می‌توانیم مشخص کنیم.)

مثال زیر کاملا گویای این نوع داده است:

// defined array with generics data type.
type UserName<T> = T[];
// After defined generics type, we can define specific data type.
const userName: UserName<string> = ["pikachu", "Raichu", "Charizard"];

// Above code is the same as this.
const userName: string[] = ["pikachu", "Raichu", "Charizard"];

در تایپ‌اسکریپت با استفاده از T می‌توانیم نوع داده‌های generics را تعریف کنیم.

مثال زیر زیاد خوب نیست و نباید از این نسبت دادن داده‌ها به متغیرها استفاده کرد. اما فقط به عنوان مثال، می‌تواند مفهوم انواع داده‌های generics را به خوبی برساند. این مثال را با هم بررسی می‌کنیم:

// defined array with generics data type.
type user<T> = T[];
// After defined generics type, we can define specific data type.
const user01: user<string> = ["pikachu", "Raichu", "Charizard"];
const user02: user<number> = [6, 14, 16];
const user03: user<boolean> = [true, true, false];

این مثال نشان می‌دهد که بعد از تعریف متغیر user به عنوان یک داده‌ی generics، این متغیر می‌تواند هر نوعی را دریافت کند. اما بعد از تعیین اولین نوع داده‌ی این متغیر، نمی‌تواند نوع دیگری بپذیرد و به خطا می‌خورد. و به نوعی این رفتار در TypeScript طبیعی است.

نوع داده‌ی Union در تایپ اسکریپت چیست؟

نوع داده union به این صورت است که می‌توانیم چندین نوع داده تعریف کنیم. مثال ساده‌ی زیر به درک بهتر این نوع داده کمک می‌کند و با هم آن را بررسی می‌کنیم:

let userName: (string | number) = "pikachu";  // OK
userName = 6; 

این قطعه کد به خوبی و بدون خطا اجرا می‌شود. زیرا متغیر userName می‌تواند هر دو نوع داده‌ی Number و String را داشته باشد. پس Union به این معناست که یک متغیر می‌تواند چندین نوع داده را بپذیرد.

اما کد زیر درست نیست و به خطا برمی‌خوریم:

let userName: (string | number) = "pikachu";
userName = 6;
userName = false;      // NG

این بدیهی است. زیرا این متغیر نمی‌تواند نوع داده‌ی Boolean را بپذیرد.

اگر بخواهیم در بخش‌هایی از پروژه، آرایه‌ای تعریف کنیم که مقادیر مختلف با انواع داده‌های مختلف داشته باشد، یقینا نوع داده‌ی union به کمک ما خواهد آمد.

مثال زیر را با هم ببینیم:

// define data type with array and union
let userName: (string | number)[] = ["pikachu", "Raichu", 6, 14];

این قطعه کد کاملا درست است. اما زمانی که در این آرایه یک نوع داده‌ی دیگر اضافه شود، به خطای type error برمی‌خوریم:

// define data type with array and union
let userName: (string | number)[] = ["pikachu", "Raichu", 6, 14, false];

خطا:

typescript.ts:105:65 - error TS2322: Type 'boolean' is not assignable to type 'string | number'.

105 let userName: (string | number)[] = ["pikachu", "Raichu", 6, 14, false];

نوع داده‌ی تاپل (Tuple) در تایپ اسکریپت چیست؟

Tuple یک نوع داده‌ی خیلی محدود است. برای درک بهتر این نوع داده، در ابتدا مثال زیر را درنظر می‌گیریم:

let userName: [string, number] = ["pikachu", 6];

در این مثال، نوع داده‌ی tuple اجازه می‌دهد که تنها دو المان با نوع داده‌های String (تنها در سمت چپ) و Number (تنها در سمت راست)  تعریف کنیم. این نوع داده را می‌توان با [ ] مشخص و استفاده کرد.

چندین مثال که منجر به خطا می‌شوند را با هم بررسی می‌کنیم:

مثال1:

let userName1: [string, number] = [6, "pikachu"];

خطا:

typescript.ts:109:36 - error TS2322: Type 'number' is not assignable to type 'string'.

109 let userName1: [string, number] = [6, "pikachu"];      // NG
                                       ~

typescript.ts:109:39 - error TS2322: Type 'string' is not assignable to type 'number'.

109 let userName1: [string, number] = [6, "pikachu"];      // NG
                                         ~~~~~~~~~

مثال2:

let userName2: [string, number] = ["pikachu", "text"]; // NG

خطا:

typescript.ts:110:47 - error TS2322: Type 'string' is not assignable to type 'number'.

110 let userName2: [string, number] = ["pikachu", "text"]; // NG
                                                 ~~~~~~

مثال3:

let userName3: [string, number] = ["pikachu", 6, 14];  // NG

خطا:

typescript.ts:111:5 - error TS2322: Type '[string, number, number]' is not assignable to type '[string, number]'.
  Source has 3 element(s) but target allows only 2.

111 let userName3: [string, number] = ["pikachu", 6, 14];  // NG

با بررسی مثال‌های بالا، کاملا واضح است که نوع داده‌ی Tuple در تایپ اسکریپت در این آرایه چه کاربردی دارد. برای توضیح بیشتر، این آرایه با نوع داده‌ی Tuple مشخص شده و می‌تواند تنها دو المان در آرایه داشته باشد. اولین مقدار در آرایه باید از نوع string و دومین مقدار در آرایه باید از نوع number باشد.

نتیجه گیری

در این مقاله، مفاهیم اولیه درباره انواع داده‌ها در تایپ اسکریپت را با هم خواندیم. اگر تایپ‌اسکریپت را یاد بگیرید، می‌توانید کدهای خواناتر و بدون خطا بنویسید.

اگر در شرکت‌های بزرگ مشغول به کار هستید و در پروژه‌های خود خط‌های زیادی کد دارید، باید زمان خیلی زیادی را صرف خواندن و فهمیدن این کدها کنید. در صورتی که TypeScript به خواندن و فهمیدن این کدها کمک کرده و آن‌ها را خواناتر می‌کند.

ما در این مقاله سعی کردیم با بیانی ساده و همراه با مثال، انواع داده در تایپ اسکریپت را برایتان توضیح دهیم. این مقاله شامل مباحث اولیه و ابتدایی از تایپ اسکریپت بود.

 

من درحال نوشتن مقاله‌ی دیگری درباره ترفندها و تکنیک‌ها در تایپ اسکریپت هستم، اگر مشتاق ادامه این مطلب و توضیح مفاهیم بیشتر و پیچیده‌تر درباره تایپ اسکریپت هستید، حتما در کامنت‎‌ها برایم بنویسید.

مرسی از شما بابت وقتی که برای خواندن این مقاله گذاشتید. 😊

پیشنهادات بیشتر سکان بلاگ برای شما