יצירת טיפוסי TypeScript מסכמה
שורה תחתונה: json-schema-to-typescript ו-quicktype מוציאים `.d.ts` בפקודה אחת, אבל זו טיוטה: אופציונליות, unions, additionalProperties ותאריכים צריכים מעבר אנושי.

שורה תחתונה: ייצרו עם json-schema-to-typescript או quicktype, ואז תקנו ביד אופציונליות, unions, additionalProperties ותאריכים; שמרו על Schema כמקור ועל הטיפוסים כפלט, עם אכיפה בשלב types:check ב-CI.
פקודה אחת נותנת לכם קובץ. היא לא נותנת לכם טיפוסים נכונים.
השורה האחת
npx json-schema-to-typescript schema.json > src/types/order.d.ts
הוא מטפל ב-$ref, allOf, oneOf, anyOf, וממיר description ל-JSDoc. ליצירה בכמות עם banner ו-style נבחר, קראו ל-Node API שלו מ-build-types.mjs קטן.
quicktype היא החלופה, והיא גם יכולה להסיק סכמה מ-JSON לדוגמה:
npx quicktype -s schema schema.json -o order.ts --lang typescript
ארבעה דברים לתקן אחר כך
אופציונליות. כל דבר שאינו ב-required הופך ל-?. אבל "תמיד קיים, עשוי להיות null" ו"עשוי להיות חסר" הם חוזים שונים:
interface Order {
remark?: string | null; // may be missing
status: string;
}
אם הבקאנד תמיד שולח remark: null, הסירו את ה-? והפסיקו לגרום לכל צרכן להגן מפני undefined.
Unions בלי מבדיל. oneOf הופך בדרך כלל ל-A | B, ש-TypeScript לא יכול לצמצם בלי שדה literal. הוסיפו מאפיין type קבוע לכל ענף ב-Schema.
additionalProperties. השמטה או true לפעמים מניבים [k: string]: unknown, לפעמים any. הראשון בטוח, השני משבית בשקט את בדיקת הטיפוסים עבור האובייקט כולו.
פורמטי תאריך. format: "date-time" הוא מחרוזת על החוט. מיפוי ל-Date אומר שגם צריך דסריאליזציה, אחרת ערך הריצה נשאר מחרוזת בזמן שהטיפוס משקר.
שמרו על הכיוון קבוע
Schema הוא המקור, טיפוסים הם פלט. יצירת ה-Schema מטיפוסים שנכתבו ביד מקובלת רק אם יצירה מחדש חובה ואכופה ב-CI — אחרת שני הצדדים נסחפים ואף אחד לא יודע מה סמכותי.
שימו את זה בצינור
"types:gen": "json2ts -i schemas/ -o src/types/generated",
"types:check": "pnpm types:gen && git diff --exit-code src/types/generated"
types:check הוא החלק החשוב: שנו את ה-Schema בלי לייצר מחדש וה-CI נכשל.
שאלות ותשובות
למה הקובץ שנוצר מכיל any?
זה מגיע בדרך כלל מ-additionalProperties שמוגדר true או הושמט, שחלק מהמחוללים ממופים ל-[k: string]: any. החליפו ב-unknown או בשדות מפורשים, כי any משבית בדיקת טיפוסים עבור האובייקט כולו.
איך לתקן שדות אופציונליים אחרי היצירה?
כל דבר מחוץ ל-required הופך ל-?, אבל "תמיד קיים, עשוי להיות null" שונה מ"עשוי להיות חסר". אם הבקאנד תמיד שולח את השדה, הסירו את ה-?.
האם ה-CI צריך להיכשל כשהסכמה והטיפוסים נסחפים?
כן. סקריפט types:check שמייצר מחדש ומריץ git diff --exit-code מפיל את הבנייה ברגע שה-Schema משתנה בלי ייצור מחדש.