تايب سكريبت - تجنب الخصائص الزائدة
لدي مشكلة مع سلوك "التحقق من الخصائص الزائدة" في TypeScript. أود التأكد من أن TypeScript لا يقبل كائنًا يحتوي على خصائص إضافية.
في مثالي لواجهة بسيطة، يمكنني ببساطة اختيار البيانات المتاحة، لكن لدي الكثير من الخصائص وأود تجنب تصفيتها أثناء وقت التشغيل، هل هناك طريقة لذلك؟
type LayoutType {
margin: number;
}
const badData = {
margin: 23,
padding: 23,
}
function func(param: LayoutType) {
console.log(param);
// Here I want to use property being sure param only contains LayoutType property
}
// OK
func({ margin: 42 })
// OK : padding is detected as unwanted property
func({ margin: 42, padding: 32 })
// KO : bad data shouldn't fit
func(badData)
/* SAME */
// OK : padding is detected as unwanted property
const test1: LayoutType = { margin: 42, padding: 32 };
// KO : bad data shouldn't fit
const test2: LayoutType = badData;
ملعب
الإجابة رقم 1
يبدو أنك تريد نوع Exact. لا يأتي Typescript بهذا النوع، لكنه سهل الإنشاء:
type Exact<A, B> = A extends B
? B extends A
? A
: never
: never
هذا في الأساس يقول إنه إذا و A extends B و B extends A فإن الأنواع متطابقة، لا أحد منها مجموعة جزئية أو مجموعة فوقية للأخرى. لذلك يجب أن يسمح بهذا النوع. إذا لم تكن متطابقة، فإن النوع يكون never مما يمنع السماح بهذا النوع.
الآن كل ما عليك فعله هو جعل دالتك عامة، وفرض أن يكون الوسيط من النوع الصحيح بالضبط:
function func<T>(param: Exact<T, LayoutType>) {
console.log(param);
}
func(badData)
// Argument of type '{ margin: number; padding: number; }'
// is not assignable to parameter of type 'never'.
ملعب
قراءة أكثر صلة هنا في مشكلة تايب سكريبت رقم 12936
أخيرًا، السبب في أن المتغير الحرفي للكائن لا يعمل، بينما متغير الكائن يعمل هو أن الحرفي يتم إنشاؤه لنوع معين. لا يمكن لـ TypeScript معرفة الخصائص الإضافية لأنه لا توجد معلومات نوعية لتلك الخصائص. لذلك لا يمكن لبرنامج TypeScript استخدام تلك الخصائص، لأنها لم تُعلن بأنها موجودة.
ومع ذلك، عندما يكون الكائن متغيرًا وتكون الخصائص الإضافية معروفة، فإنه يصبح نوعًا منفصلًا ولكن متوافقًا. قد لا تُستخدم الخصائص الإضافية في دالة تقبل النوع الضيق فقط، ولكن في الشيفرة الأخرى التي تعرف عن النوع الأوسع، يمكن استخدام الخصائص.
هذا هو السبب في أن هذا صحيح:
const obj1 = { a: 1, b: 2 }
const obj2: { a: number } = obj1
console.log(obj1.b) // b can still be accessed
لكن هذا ليس:
const obj1: { a: number } = { a: 1, b: 2 }
// ^ type error
الإجابة رقم 2
السبب
func({ margin: 42, padding: 32 })
لا يعمل، لكن
func(badData)
السبب في ذلك هو شيء يُسمى "التحقق من الخصائص الزائدة" في TypeScript:
تحصل الحروف الحرفية للأشياء على معاملة خاصة وتخضع لـ فحص الخصائص الزائدة عند تخصيصها لمتغيرات أخرى، أو تمريرها كوسائط. إذا كان لحرف الشيء الحرفي أي خصائص لا يمتلكها "نوع الهدف"، فستحصل على خطأ.
