درود دوستان! توی تایپ‌اسکریپت فیچرهای واقعاً زیادی وجود داره که شاید درک کردن تفاوت بعضی از اونها شاید راحت نباشه. یکی از این شباهت‌ها، تایپ‌های void و never هستن که می‌خوایم توی این قسمت تفاوت این دو رو برررسی کنیم.

 

نکته

کدهای این قسمت رو می‌تونین از اجرا کنین.

 

تایپ void چیه؟ 🤔

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

function func1(): <<void>> {

}

function func2(): <<void>> {
  return;
}

function func3(): <<void>> {
  return undefined;
}

خروجی هر سه تابع undefined هست. همونطور که می‌دونیم توی جاوااسکریپت اگه تابعی return نداشته باشه یا یک return خالی داشته باشه، خروجی اون تابع undefined هست. توی تایپ‌اسکریپت اگه یک تابع چیزی برای ریترن کردن نداشته باشه، نوع خروجی اون به عنوان void در نظر گرفته میشه.

پس اگه نمی‌خوایم چیزی از تابع ریترن کنیم، بهتره از تایپ void بجای undefined استفاده کنیم. چون اگه نوع خروجی تابعی رو صراحتاً undefined در نظر بگیریم، حتماً باید چیزی رو ریترن کنیم. در غیر این صورت خطا می‌گیریم:

function f(): undefined {
  
}
// Error: A function whose declared type is neither 'void' nor 'any' must return a value.

 

تایپ never چیه؟ 🤔

بعضی توابع ممکنه اصلاً به مرحلهٔ ریترن کردن نرسن. مثلاً:

function fail() {
  throw new Error('Failed');

  console.log('Hi');
}

کدهای توی این تابع هیچوقت به طول کامل - از ابتدا تا انتها - اجرا نمیشن. چون توی خط ۲ یک خطا داره Throw میشه و بخاطر اون، اجرای تابع اینجا متوقف میشه و کدهای خط بعدی اجرا نمیشن. این اتفاق برای تابع زیر هم رخ میده:

function whileTrue() {
  while (true) {

  }

  // Never executed:
  console.log('Hi');
}

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

function fn(): never {
  
}

// A function returning 'never' cannot have a reachable end point.

بنابراین از تایپ never برای تابعی استفاده می‌کنیم که حدس می‌زنیم به مرحلهٔ ریترن کردن نرسه.

 

تایپ never و عملیات Narrowing

اگه یک تایپ Union داشته باشیم (مثل تایپ پارامتر x توی کد زیر) و تایپ‌اسکریپت مثل کد خط ۷ نتونه مقداری رو برای یک متغیر در نظر بگیره، نوع اون متغیر never در نظر گرفته میشه:

function fn(x: string | number) {
  if (typeof x === "string") {
    // do something
  } else if (typeof x === "number") {
    // do something else
  } else {
    x; // has type 'never'!
  }
}

توی کد بالا و توی بلاک else، متغیر x از نوع never خواهد بود. چونکه کد اصلاً به اون قسمت نمی‌رسه.

 

never در Function Expression و Function Declaration

تایپ‌اسکریپت نوع خروجی تابع زیر که یک Function Expression هست رو از نوع never در نظر می‌گیره:

const f = function () {
  throw new Error();
}

اما اگه اون رو تبدیل به یک Function Declaration کنیم، نوع خروجی اون تابع void در نظر گرفته میشه:

function f() {
  throw new Error();
}

برای بررسی، رو باز کنین و روی توابع Hover کنین.

 

به عنوان نتیجه‌گیری می‌تونیم بگیم که بطور کلی توابع void همیشه مقداری رو ریترن می‌کنن (که undefined هست). اما توابع never اصلاً به مرحلهٔ ریترن کردن نمی‌رسن.

امیدوارم از این پست هم استفاده کرده باشین. روزتون خوش 👋

 

https://www.typescripttutorial.net/typescript-tutorial/typescript-never-type

https://www.typescriptlang.org/docs/handbook/2/functions.html#void