§

نمونه JSON

در حال آماده‌سازی استنباطگر نوع…
§

Interface های TypeScript

TypeScript

تیم‌های TypeScript در شرکت‌های ایرانی مانند Shaparak و فین‌تک‌های دیگر زود به این مشکل برمی‌خورند. SDK های بزرگ با کلاینت‌های typed عرضه می‌شوند، اما سرویس‌های داخلی و payload های webhook شخص ثالث کمتر این‌طور هستند. جریان کاری معمول این است: یک پاسخ واقعی را در پنل شبکه ضبط کنید، اینجا پیست کنید، ریشه را پس از endpoint نام‌گذاری کنید، و خروجی را به پوشه types پروژه کپی کنید. از آنجا، حالت strict عدم‌تطابق‌هایی را که مستندات فراموش کرده بودند ذکر کنند شناسایی می‌کند. استنباطگر کاملاً در مرورگر شما اجرا می‌شود، بنابراین payload های API staging، بدنه‌های webhook امضاشده و endpoint های منتشرنشده هرگز به یک سرویس میزبانی نمی‌رسند.

نحوه کار استنباط JSON به TypeScript

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

  1. تجزیه نمونه JSON با پارسر بومی مرورگر و رد ورودی نادرست با راهنمای خط/ستون.
  2. تشخیص یک نوع TypeScript برای هر مقدار — string، number، boolean، null، آرایه یا شیء تودرتو.
  3. دادن یک نام interface به هر شیء تودرتو که از کلید ویژگی والد مشتق شده است (بنابراین user.address به یک interface به نام Address تبدیل می‌شود).
  4. ادغام نوع آیتم‌ها در هر آرایه تا یک لیست از {id: 1} و {id: 2, label: "x"} یک union با فیلدهای اختیاری مناسب تولید کند.
  5. اعمال گزینه‌های شما (interface در مقابل type، readonly، اختیاری-nullable) و انتشار اعلان‌ها به ترتیب وابستگی تا فایل بدون ارجاع‌های پیش‌رو کامپایل شود.

چرا نوع TypeScript را از JSON تولید کنیم؟

  • اکثر باگ‌های شکل در زمان کامپایل قابل شناسایی هستند اگر نوع پاسخ نوشته شده باشد. استنباط یک interface از یک payload واقعی بیشتر کار را برای شما انجام می‌دهد، و حالت `strict` فیلدی را که مستندات فراموش کرده بودند ذکر کنند شناسایی می‌کند.
  • جفت کردن interface های استنباط‌شده با یک اعتبارسنج runtime مانند Zod یا io-ts یک شکل را دو وظیفه می‌دهد: تکمیل خودکار ویرایشگر در توسعه و یک خطای ۴۰۰ در لبه وقتی تولید چیز غیرمنتظره‌ای ارسال می‌کند.
  • سرور زبان TypeScript فقط فیلدهایی را نمایش می‌دهد که می‌شناسد. وقتی interface استنباط‌شده را import کنید، تکمیل خودکار درست وقتی نقطه را تایپ می‌کنید کار می‌کند — دیگر هیچ cast به `as any` روی پاسخ و grep ناامیدکننده در سراسر مخزن لازم نیست.
  • اگر می‌خواهید یک مشخصات OpenAPI بنویسید، یک interface استنباط‌شده یک پیش‌نویس اولیه سریع از schema پاسخ است. هنوز به مثال‌ها و محدودیت‌های دست‌نوشته نیاز خواهید داشت، اما نام ویژگی‌ها و نوع‌ها از قبل درست هستند.

کاربردهای رایج

استنباط بیشتر در مواقعی کمک می‌کند که یک payload واقعی وجود دارد اما schema وجود ندارد.

  • تایپ کردن payload های webhook شخص ثالث از Stripe، GitHub یا Twilio قبل از نوشتن handler.
  • راه‌اندازی اولیه نوع‌ها برای یک REST API داخلی تا تیم frontend بتواند همان روزی که backend آماده شد شروع به کدنویسی کند.
  • تولید نقطه شروع برای یک schema Zod، io-ts یا Valibot از پاسخ مشاهده‌شده API.

خروجی چه شکلی است؟

با یک سند JSON نمونه و یک نام ریشه، مولد یک درخت از interface ها تولید می‌کند، یکی به ازای هر شیء تودرتو. برای ورودی زیر با نام ریشه User:

پیست کردن {"id":1,"name":"Alice","tags":["a","b"],"address":{"city":"Paris"}} با نام ریشه User مولد تولید می‌کند:

export interface User {
  id: number;
  name: string;
  tags: string[];
  address: Address;
}

export interface Address {
  city: string;
}
توجه کنید که address به interface نام‌گذاری‌شده مستقل ارتقا یافت — این خروجی مرتب‌شده بر اساس وابستگی است. همان JSON با سبک اعلان type به جای آن export type User = {...} تولید می‌کند؛ با تاگل readonly روشن، هر ویژگی تغییردهنده readonly را دریافت می‌کند.

گزینه‌های مولد

سبک اعلان

انتخاب کنید interface (اصطلاح استاندارد TypeScript برای شکل‌های شیء) یا type (مفید اگر بعداً به mapped type ها، conditional type ها یا intersection ها نیاز داشتید). هر دو رفتار یکسانی در runtime دارند؛ انتخاب یک ترجیح سبک کدنویسی است.

فیلدهای nullable اختیاری

وقتی یک مقدار نمونه‌برداری‌شده null است، نوع فیلد T | null می‌شود. روشن کردن این گزینه همچنین یک تغییردهنده ? اضافه می‌کند تا فیلد در سمت TypeScript اختیاری باشد — مفید وقتی API گاهی کلید را کاملاً حذف می‌کند به جای بازگرداندن null.

تغییردهنده Readonly

پیشوند readonly را به هر اعلان ویژگی اضافه می‌کند تا interface منتشرشده با یک مدل داده غیرقابل‌تغییر مطابقت داشته باشد. مفید برای slice های حالت Redux، پاسخ‌های API frozen شده یا هر جایی که می‌خواهید کامپایلر mutation تصادفی را علامت‌گذاری کند.

آیا از شیءهای تودرتو و آرایه‌ها پشتیبانی می‌کند؟

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

فیلدهای اختیاری چگونه استنباط می‌شوند؟

تاگل «فیلدهای null-پذیر را اختیاری علامت‌گذاری کن» را روشن کنید و هر فیلدی که مقدار نمونه‌برداری‌شده‌اش null است یک تغییردهنده ? روی کلید به اضافه | null در نوع دریافت می‌کند. بدون تاگل، فیلد ضروری باقی می‌ماند و نوع فقط T | null است.

آیا از union های تمایزگذاری‌شده پشتیبانی می‌کند؟

union type های پایه وقتی یک آرایه آیتم‌هایی با شکل مختلط دارد یا وقتی یک فیلد هم یک مقدار و هم null حمل می‌کند ایجاد می‌شوند. استنباط کامل discriminated-union (انتخاب type یا kind به عنوان تگ و تقسیم variant ها) به چندین نمونه نیاز دارد — این برنامه‌ریزی شده اما در build امروز نیست.

آیا می‌توانم نوع‌ها را از چندین نمونه JSON استنباط کنم؟

هنوز نه — استنباطگر امروز یک نمونه را در یک زمان می‌خواند. اگر دو payload دارید که باید یک interface را به اشتراک بگذارند (مثلاً، یک endpoint لیست و یک endpoint آیتم واحد)، راه‌حل عملی این است که آن‌ها را در یک آرایه ادغام کنید، از آن تولید کنید، و سپس union type های حاصل را تغییر نام دهید. استنباط چند-نمونه‌ای در نقشه راه است زیرا تنها راه تشخیص فیلدهایی است که در یک پاسخ حضور دارند و در پاسخ دیگر غایب هستند.

یک payload پیست کنید، ریشه را نام‌گذاری کنید، interface ها را کپی کنید. کل خط لوله در مرورگر شما اجرا می‌شود، بنابراین یک API منتشرنشده یا یک بدنه webhook امضاشده روی دستگاه شما باقی می‌ماند.