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

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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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 '() => { 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 '() => { 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'.

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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
type ExampleFunction = () => {
something: {
excellent: string
awesome: number
}
}
const exampleFunc: ExampleFunction = () => {
// ^^^^^^^^^^^ Error here!
return {
something: {
excellent: 'str',
awesome: true,
},
}
}
type ExampleFunction = () => { something: { excellent: string awesome: number } } const exampleFunc: ExampleFunction = () => { // ^^^^^^^^^^^ Error here! return { something: { excellent: 'str', awesome: true, }, } }
type ExampleFunction = () => {
  something: {
    excellent: string
    awesome: number
  }
}

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

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

اتفاقی که در اینجا می‌افتد این است که می‌گوییم

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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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 '() => { 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 '() => { 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
exampleFunc) را با یک تایپ (
ExampleFunction
ExampleFunction) مقایسه می‌کنیم، با تابع شروع می‌شود:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Type '() => { something: { excellent: string; awesome: boolean; }; }' is not assignable to type 'ExampleFunction'.
Type '() => { something: { excellent: string; awesome: boolean; }; }' is not assignable to type 'ExampleFunction'.
Type '() => { something: { excellent: string; awesome: boolean; }; }' is not assignable to type 'ExampleFunction'.

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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Call signature return types '{ something: { excellent: string; awesome: boolean; }; }' and '{ something: { excellent: string; awesome: number; }; }' are incompatible.
Call signature return types '{ something: { excellent: string; awesome: boolean; }; }' and '{ something: { excellent: string; awesome: number; }; }' are incompatible.
Call signature return types '{ something: { excellent: string; awesome: boolean; }; }' and '{ something: { excellent: string; awesome: number; }; }' are incompatible.

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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
The types of 'something.awesome' are incompatible between these types.
The types of 'something.awesome' are incompatible between these types.
The types of 'something.awesome' are incompatible between these types.

در این صورت مشکل ویژگی تو در تو

something.awesome
something.awesomeچیست؟

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Type 'boolean' is not assignable to type 'number'.
Type 'boolean' is not assignable to type 'number'.
Type 'boolean' is not assignable to type 'number'. 

بالاخره به ریشه مشکل رسیدیم. برای رفع آن، باید

awesome: true
awesome: trueرا به
awesome: 123
awesome: 123یا مورد مشابه تغییر دهیم.

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

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

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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const exampleFunc: ExampleFunction = () => {
// ^^^^^^^^^^^ Red line here...
return {
something: {
excellent: 'str',
awesome: true,
//^^^^^ ...but this was the cause.
},
}
}
const exampleFunc: ExampleFunction = () => { // ^^^^^^^^^^^ Red line here... return { something: { excellent: 'str', awesome: true, //^^^^^ ...but this was the cause. }, } }
const exampleFunc: ExampleFunction = () => {
  //  ^^^^^^^^^^^ Red line here...
  return {
    something: {
      excellent: 'str',
      awesome: true,
      //^^^^^ ...but this was the cause.
    },
  }
}

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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
type ExampleReturnType = {
something: {
excellent: string
awesome: number
}
}
const example = (): ExampleReturnType => {
return {
something: {
excellent: 'str',
awesome: true,
//^^^^^ Type 'boolean' is not assignable to type 'number'.
},
}
}
type ExampleReturnType = { something: { excellent: string awesome: number } } const example = (): ExampleReturnType => { return { something: { excellent: 'str', awesome: true, //^^^^^ Type 'boolean' is not assignable to type 'number'. }, } }
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 شوند، بنابراین تایپ اسکریپت می‌تواند خطای طولانی را کنار بگذارد و فقط خطی که مهم است را نشان دهد:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Type 'boolean' is not assignable to type 'number'.
Type 'boolean' is not assignable to type 'number'.
Type 'boolean' is not assignable to type 'number'.

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

دیدگاه‌ها:

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