بررسی ساختار خطا در تایپ اسکریپت

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

Type '() => { something: { excellent: string; awesome: boolean; }; }' is not assignable to type 'ExampleFunction'.
  Call signature return types '{ something: { excellent: string; awesome: boolean; }; }' and '{ something: { excellent: string; awesome: number; }; }' are incompatible.
    The types of 'something.awesome' are incompatible between these types.
      Type 'boolean' is not assignable to type 'number'.

در ادامه کدی که باعث این خطا شده است را داریم:

type ExampleFunction = () => {
  something: {
    excellent: string
    awesome: number
  }
}

const exampleFunc: ExampleFunction = () => {
  //  ^^^^^^^^^^^ Error here!
  return {
    something: {
      excellent: 'str',
      awesome: true,
    },
  }
}

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

اتفاقی که در اینجا می‌افتد این است که می‌گوییم exampleFuncباید از تایپ ExampleFunctionباشد و به این ترتیب یک خطا دریافت می‌کنیم. با بررسی آن متوجه می‌شویم که به چند بخش که دارای تورفتگی است تقسیم می‌شود:

Type '() => { something: { excellent: string; awesome: boolean; }; }' is not assignable to type 'ExampleFunction'.

---

Call signature return types '{ something: { excellent: string; awesome: boolean; }; }' and '{ something: { excellent: string; awesome: number; }; }' are incompatible.

---

The types of 'something.awesome' are incompatible between these types.

---

Type 'boolean' is not assignable to type 'number'.

این ساختار، ساختار کد را منعکس می‌کند. از آنجایی که ما یک تابع (exampleFunc) را با یک تایپ (ExampleFunction) مقایسه می‌کنیم، با تابع شروع می‌شود:

Type '() => { something: { excellent: string; awesome: boolean; }; }' is not assignable to type 'ExampleFunction'.

سوالی که مطرح می‌شود این است که چرا تابعی که داریم قابل تخصیص(assignable) نیست؟ این موضوع به دلیل تاثیر return می‌باشد.

Call signature return types '{ something: { excellent: string; awesome: boolean; }; }' and '{ something: { excellent: string; awesome: number; }; }' are incompatible.

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

The types of 'something.awesome' are incompatible between these types.

در این صورت مشکل ویژگی تو در تو something.awesomeچیست؟

Type 'boolean' is not assignable to type 'number'. 

بالاخره به ریشه مشکل رسیدیم. برای رفع آن، باید awesome: trueرا به awesome: 123یا مورد مشابه تغییر دهیم.

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

چگونه می‌توانیم پیچیدگی خطاها را کم‌تر کنیم؟

در مثال بالا، می‌توانیم ببینیم که مشکل واقعی تا حدودی از علت فاصله دارد:

const exampleFunc: ExampleFunction = () => {
  //  ^^^^^^^^^^^ Red line here...
  return {
    something: {
      excellent: 'str',
      awesome: true,
      //^^^^^ ...but this was the cause.
    },
  }
}

تایپ اسکریپت مجبور بود برای توضیح کل ساختار خطا، یک خطای طولانی را ایجاد کند. ما می‌توانیم با تغییر روش تخصیص تایپ، پیچیدگی خطا را کاهش دهیم:

type ExampleReturnType = {
  something: {
    excellent: string
    awesome: number
  }
}

const example = (): ExampleReturnType => {
  return {
    something: {
      excellent: 'str',
      awesome: true,
      //^^^^^ Type 'boolean' is not assignable to type 'number'.
    },
  }
}

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

آبجکت‌ها پیچیده‌تر از توابع هستند. آن‌ها نمی‌توانند overloade شوند، بنابراین تایپ اسکریپت می‌تواند خطای طولانی را کنار بگذارد و فقط خطی که مهم است را نشان دهد:

Type 'boolean' is not assignable to type 'number'.

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

دیدگاه‌ها:

افزودن دیدگاه جدید