ایجاد پویا رابط ها و طرحواره های اعتبار سنجی در TypeScript با Yup

پیشنهاد ویژه
[button color="primary" size="big" link="https://nabfollower.com/buy-real-follower/" icon="" target="true" follow="false"]خرید فالوور واقعی[/button][button color="primary" size="big" link="https://nabfollower.com/buy-instagram-like/" icon="" target="true" follow="false"]خرید لایک اینستاگرام[/button][button color="primary" size="big" link="https://nabfollower.com/buy-instagram-views/" icon="" target="true" follow="false"]خرید ویو اینستاگرام[/button][button color="primary" size="big" link="https://nabfollower.com/" icon="" target="true" follow="false"]خرید فالوور اینستاگرام[/button]
در یک پروژه اخیر، من با مشکلی مواجه شدم که در آن باید یک شی را با کلیدهایی که به صورت پویا توسط یک نقشه ثابت تعریف شده اند تأیید کنیم و حداقل یک کلید دارای مقدار معتبری باشد.
چالش
ما یک شی MetadataMap داشتیم که کلیدهای معتبر و انواع مربوط به آنها را تعریف می کرد:
const MetadataMap = {
userId: Number,
utmSource: String,
utmMedium: String,
utmCampaign: String,
} as const;
از این نقشه، ما نیاز داشتیم:
- به صورت پویا یک رابط TypeScript ایجاد کنید تا ایمنی نوع را اعمال کنید.
- یک طرح اعتبارسنجی Yup ایجاد کنید که شی را بر اساس نقشه تأیید می کند.
- اطمینان حاصل کنید که حداقل یک کلید در شی دارای یک مقدار معتبر و تعریف نشده است.
- از کلیدهای کدگذاری سخت اجتناب کنید تا راه حل قابل نگهداری باشد.
اما، TypeScript انواع استاتیک را در زمان کامپایل اعمال می کند، در حالی که Yup اعتبار سنجی زمان اجرا را کنترل می کند.
مرحله 1: ایجاد رابط
برای تولید رابط TypeScript از MetadataMap، از انواع keyof و نگاشت شده استفاده کردیم. در اینجا نحوه تعریف آن آمده است:
type Metadata = {
[K in keyof typeof MetadataMap]: typeof MetadataMap[K] extends NumberConstructor
? number
: string;
};
این رویکرد تضمین میکند که هر بهروزرسانی به MetadataMap به طور خودکار در رابط Metadata منعکس میشود. به عنوان مثال:
// Resulting Metadata interface:
interface Metadata {
userId?: number;
utmSource?: string;
utmMedium?: string;
utmCampaign?: string;
}
مرحله 2: ایجاد پویا طرحواره Yup
ما نیاز داشتیم که به صورت پویا طرحی Yup ایجاد کنیم که با کلیدها و انواع موجود در MetadataMap مطابقت داشته باشد. با استفاده از Object.keys و یک کاهنده، هر کلید را به اعتبارسنجی Yup مربوطه نگاشت کردیم:
const metadataSchema = Yup.object(
Object.keys(MetadataMap).reduce((schema, key) => {
const type = MetadataMap[key as keyof typeof MetadataMap];
if (type === Number) {
schema[key] = Yup.number().optional();
} else if (type === String) {
schema[key] = Yup.string().optional();
}
return schema;
}, {} as Record
);
این روش کدگذاری سخت را حذف کرد و تضمین کرد که تغییرات در MetadataMap بدون به روز رسانی دستی در طرح منعکس می شود.
مرحله 3: اضافه کردن قانون “حداقل یک کلید”.
چالش بعدی حصول اطمینان از این بود که حداقل یک کلید در شی دارای یک مقدار تعریف شده باشد. ما یک روش .test را به طرح Yup اضافه کردیم:
metadataSchema.test(
"at-least-one-key",
"Metadata must have at least one valid key.",
(value) => {
if (!value || typeof value !== "object") return false;
const validKeys = Object.keys(MetadataMap) as (keyof typeof MetadataMap)[];
return validKeys.some((key) => key in value && value[key] !== undefined);
}
);
این منطق:
- از معتبر بودن شی اطمینان می دهد.
- کلیدهای معتبر را به صورت پویا از MetadataMap استخراج می کند.
- تأیید می کند که حداقل یک کلید دارای مقدار نامشخصی است.
نتیجه
در اینجا نحوه رفتار طرحواره نهایی آمده است:
const exampleMetadata = {
userId: undefined,
utmSource: "google",
extraField: "invalid", // This key is ignored.
};metadataSchema
.validate(exampleMetadata)
.then(() => console.log("Validation succeeded"))
.catch((err) => console.error("Validation failed:", err.errors));
در این مثال، اعتبارسنجی موفقیت آمیز است زیرا utmSource یک کلید معتبر با مقدار تعریف نشده است، حتی اگر userId تعریف نشده باشد و extraField بخشی از MetadataMap نیست.