لماذا يقوم عامل التشغيل && بإنتاج نوع المعامل الثاني
-
12-12-2019 - |
سؤال
تنص مواصفات TypeScript في الفقرة 4.15.6 على &&
المشغل أو العامل:
يسمح عامل التشغيل && للمعاملات بأن تكون من أي نوع وينتج ملف نتيجة من نفس نوع المعامل الثاني.
في جافا سكريبت، &&
يقوم عامل التشغيل بإرجاع المعامل الأول إذا كان خطأ، وإلا فإنه يقوم بإرجاع المعامل الثاني (انظر ECMA-262 §11.11).
وهذا يعني أنه إذا كان المعامل الأيسر خطأ، &&
سيُرجع قيمة تطابق نوع المعامل الأيسر.على سبيل المثال،
typeof ( false && {} ) === "boolean" // true
typeof ( '' && 1 ) === "string" // true
typeof ( null && "hello" ) === "object" // true
typeof ( NaN && true ) === "number" // true
الآلة الكاتبة، وفقًا للقاعدة المذكورة أعلاه، ستكون كذلك بشكل غير صحيح التنبؤ بأنواع التعبيرات المذكورة أعلاه Object
, Number
, String
و Boolean
, ، على التوالى.
هل فاتني شيء؟هل هناك سبب وجيه لجعل نوع &&
هل يتطابق التعبير مع نوع المعامل الثاني؟ألا ينبغي أن يتصرف نوع النتيجة مثل ||
عامل التشغيل، وإرجاع أفضل نوع شائع بين المعاملين، و Any
إذا لم يكن هناك أفضل نوع مشترك؟
المحلول
باختصار، لا يوجد حل هنا يرضي الجميع.
خذ بعين الاعتبار هذا المصطلح الشائع:
var customer = GetCustomer(...); // of type 'Customer'
var address = customer && customer.address;
if(address) {
printAddressLabel(address); // Signature: (Address) => void
} else {
// Couldn't find the customer or the customer has no address on file
}
سيكون أمرًا ضعيفًا جدًا أن تستسلم وتقرر أن "العنوان" هو "أي" لأنه لا يوجد أفضل نوع مشترك بين العميل والعنوان.
في معظم الحالات التي يتم فيها استخدام عامل التشغيل &&، يتم استخدام أي من النوعين بالفعل match، أو && يتم استخدامه بطريقة دمج القيمة كما هو مذكور أعلاه.وفي كلتا الحالتين، فإن إرجاع نوع المعامل الصحيح يمنح المستخدم النوع المتوقع.
على الرغم من أن أمان النوع ينهار من الناحية الفنية في هذه المرحلة، إلا أنه لا يفعل ذلك بطريقة من المحتمل أن تؤدي إلى حدوث خطأ.إما أنك ستختبر القيمة الناتجة للصدق (وفي هذه الحالة يكون النوع غير ذي صلة إلى حد ما)، أو أنك ستستخدم المعامل الصحيح المفترض لبعض العمليات (المثال أعلاه يقوم بكلا الأمرين).
إذا نظرنا إلى الأمثلة التي ذكرتها وتظاهرنا بأن المعامل الأيسر صحيح أو خطأ بشكل غير محدد، ثم حاولنا كتابة تعليمات برمجية معقولة تعمل على القيمة المرجعة، يصبح الأمر أكثر وضوحًا - ليس هناك الكثير مما يمكنك فعله يفعل مع "خطأ && {}" الذي لا يدخل بالفعل في موضع حجة "أي" أو اختبار الصدق.
إضافة
وبما أن بعض الناس لم يقتنعوا بما ورد أعلاه، فإليك تفسيرًا مختلفًا.
دعونا نتظاهر للحظة أن نظام كتابة TypeScript أضاف ثلاثة أنواع جديدة: Truthy<T>
, Falsy<T>
, ، و Maybe<T>
, ، يمثل قيم الصدق/الخطأ المحتملة للنوع T
.قواعد هذه الأنواع هي كما يلي:
Truthy<T>
يتصرف بالضبط مثلT
- لا يمكنك الوصول إلى أي خصائص
Falsy<T>
- تعبير عن النوع
Maybe<T>
, ، عند استخدامها كشرط فيif
كتلة، تصبحTruthy<T>
في جسد ذلك الشيء نفسهif
كتلة و أFalsy<T>
في الelse
حاجز
وهذا من شأنه أن يتيح لك القيام بأشياء مثل هذا:
function fn(x: Maybe<Customer>) {
if(x) {
console.log(x.address); // OK
} else {
console.log(x.phone); // Error: x is definitely falsy
}
console.log(x.name); // Warning: x might be falsy!
}
جيد جدا حتى الآن.يمكننا الآن معرفة قواعد الكتابة للمشغل &&.
Truthy<T> && x
يجب أن يكون خطأ - إذا كان الجانب الأيسر معروفًا بأنه صادق، فيجب أن تكون قد كتبت للتوx
Falsy<T> && x
يجب أن يكون خطأ - إذا كان الجانب الأيسر معروفا بأنه كاذب،x
هو رمز لا يمكن الوصول إليهMaybe<T> && x
ينبغي أن تنتج ...ماذا؟
نحن نعرف النتيجة Maybe<T> && x
ستكون إما قيمة زائفة من النوع T
, ، أو x
.لا يمكنها أن تنتج Truthy<T>
(إلا إذا T
== النوع x
وفي هذه الحالة تكون هذه المناقشة بأكملها موضع نقاش).دعونا نسمي هذا النوع الجديد Falsy<T> XOR Maybe<U>
.
ما ينبغي أن قواعد Falsy<T> XOR Maybe<U>
يكون؟
- من الواضح أنه لا يمكنك استخدام خصائص
T
عليه.إذا كانت القيمة من النوعT
, ، فهو زائف، وغير آمن للاستخدام. - يجب أن تكون قادرًا على استخدامه ك
Maybe<U>
, ، منذFalsy<T>
وFalsy<U>
لديهم نفس السلوكيات - لا يجب أن تكون قادرًا على استخدام خصائص
U
, ، لأن القيمة لا تزال غير صحيحة. - إذا كنت تستخدمه في
if
اختبار، ثم ينبغي أن تصبحTruthy<U>
في كتلة ذلكif
إفادة
بعبارة أخرى، Falsy<T> XOR Maybe<U>
يكون Maybe<U>
.ويتبع كل نفس القواعد.لا تحتاج إلى تعقيد نظام الكتابة على الإطلاق هنا بإضافة هذا الغريب XOR
النوع، لأن النوع الذي يناسب جميع المواصفات التي تحتاجها موجود بالفعل.
هذا يشبه إلى حد ما إعطاء شخص ما صندوقًا والقول "هذا إما صندوق فارغ من القمامة، أو صندوق كامل من المواد القابلة لإعادة التدوير".يمكنك تفريغ محتويات الصندوق بأمان في سلة إعادة التدوير.