اگر روی library code کار می‌کنیم، قطعاً می‌خواهیم typeهای خود را تست کنیم. typeها بخش مهمی از API هستند که آن‌ها را در معرض دید کاربران قرار می‌دهیم و می‌خواهیم مطمئن شویم که منطق ما در سطح type کار می‌کند. در این مقاله قصد داریم تا با تست نویسی type آشنا شویم.

Vitest

یکی از روش‌هایی که می‌توانیم با استفاده از آن typeهای خود را تست کنیم استفاده از vitest است. Vitest یک test runner بسیار قدرتمند و محبوب بر اساس Vite می‌باشد. در حال حاضر Vitest به طور گسترده برای تست کد زمان اجرا مورد استفاده قرار می‌گیرد. پس ما چرا از آن برای تست typeهای خود استفاده نکنیم؟ Vitest با چندین API عرضه می‌شود که به ما این امکان را می‌دهد تا برای typeهای خود تست نویسی انجام دهیم.

import { assertType, expectTypeOf } from "vitest";
import { mount } from "./mount";
test("my types work properly", () => {
  expectTypeOf(mount).toBeFunction();
  expectTypeOf(mount).parameter(0).toMatchTypeOf<{ name: string }>();
});

این کار بسیار جالب است و وجود آن در یک test runner واقعا ارزشمند می‌باشد، زیرا این امکان را به ما می‌دهد تا تست‌های مروبوط به type را با تست‌های زمان اجرا ترکیب کنیم.

استفاده از راه حل شخصی خود

اگر برای تست نویسی type از vitest استفاده نمی‌کنیم، می‌توانیم راه‌حل خودمان را بسازیم.

فرض کنید در حال تست type یک مورد هستیم. برای این کار می‌توانیم از type helperها مانند Expectو Equalاستفاده کنیم تا type مورد نظر خود را محدود نماییم.

type Expect<T extends true> = T;
type Equal<X, Y> = Expect<X extends Y ? (Y extends X ? true : false) : false>;
// Example
const identityFunc = <T>(arg: T) => arg;
it("Should return whatever you pass in", () => {
  const test1 = identityFunc("hello");
  type test = Expect<Equal<typeof test1, "hello">>;
});

اگر خطایی دریافت کنیم، آن را به صورت خط با رنگ قرمز در IDE خواهیم دید. به عنوان بخشی از مجموعه تستی خود، می‌توانیم tsc(the TypeScript CLI) را روی کل مجموعه اجرا کرده و بررسی نماییم که آیا هر یک از تست‌های type ما با شکست مواجه شده است یا خیر.

همچنین می‌توانیم با استفاده از ts-expect-errorبررسی کنیم که چیزی در تایپ اسکریپت کار نمی‌کند. این یک کامنت مخصوص است که می‌توانیم آن را روی یک خط اضافه کنیم تا خط بعدی را ببینیم. اگر خطایی در خط بعدی مشاهده نکند، با شکست مواجه می‌شود. ما می‌توانیم از این موضوع برای بررسی اینکه آیا چیزی مجاز است یا نه و ادعا این که در موقعیت‌های خاص خطا رخ داده است، استفاده کنیم.

const myFunc = <T extends string>(arg: T) => {};
it("Should not accept a number", () => {
  // @ts-expect-error
  myFunc(123);
});

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

Tsd

در نهایت، یک کتابخانه پرکاربرد به نام tsd وجود دارد که به ما کمک می‌کند تا typeهای خود را تست کنیم. در واقع بسیار شبیه به vitest عمل می‌کند، اما این در همه چیز ادغام شده و کار کردن با آن را آسان‌تر می‌کند.

جمع‌بندی

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