Typescript: من المستحيل تحديد دالة "طول" ثابتة في الفصل

تم إنشاؤها على ١٢ أغسطس ٢٠١٤  ·  22تعليقات  ·  مصدر: microsoft/TypeScript

يتم قبول برنامج الكتابة المطبوعة التالية:

class C {
    static length ()  { return "twelve"; }
}

ومع ذلك ، في الكود الذي تم إنشاؤه:

var C = (function () {
    function C() {
    }
    C.length = function () {
        return "twelve";
    };
    return C;
})();

هنا ، جرت محاولة لتعيين خاصية length للدالة. هذا لا يعمل (على الأقل في Firefox و Chrome) ، مما تسبب في تعطل المكالمات اللاحقة C.length() . ربما يجب فقط عدم السماح باستدعاء وظيفة فئة ثابتة length ؟

تم الترحيل من إصدار codeplex

Bug Fixed good first issue help wanted

التعليق الأكثر فائدة

وفي الوقت نفسه ، وصل الدعم الأصلي ES6 / 2015 إلى Chrome و Firefox. إذا لاحظنا كيف يتعامل هؤلاء مع المشكلة في الأصل ، فسيكون قريبًا مما اقترحه @ nicolo-ribaudo وأنا (انظر # 9778)

مقتطف لتوضيح السلوك الأصلي:

class Foo {
    constructor() {}
}
class Bar {
    static length() {}
    static name() {}
    static caller() {}
}
Foo.name = "FooChanged";
Bar.name = "Baz";

console.log(Foo.name) // Logs "Foo". Foo.name remains unwritable
console.log(Bar.name) // Logs "Baz".  Bar.name became writable

فيما يتعلق بما كتبه tinganho سابقًا عن القراءة فقط لـ name و length و caller يمكننا ملاحظة أن الخصائص قابلة للكتابة على دالة المُنشئ مرة واحدة لقد حددنا أيًا من هؤلاء على أنه عضو في فئة ثابتة (لا تتردد في مراجعة أو تعديل تحذيراتي الأخيرة على MDN فيما يتعلق بالافتراضات الخطيرة حول Function.name للحصول على اسم فئة ، بسبب هذا).

لذا فإن استخدام Object.defineProperty كما اقترحه @ nicolo-ribaudo سيحاكي السلوك المحلي بدقة. الشيء الذي يجب مراعاته هو أن بعض إصدارات المستعرضات الأقدم ولكن المتوافقة مع ES5 قد حددت الخصائص لتكون configurable: false . لذا فإن محاولة جعلهم writable: true ستفشل بالنسبة لهم (على سبيل المثال ، انظر قابلية تكوين Function.name )

لتلخيص الأمور ، كان رأيي في هذه القضية:

  • لا يمكننا استخدام Object.defineProperty() للهدف التجميعي es3 . بدون Object.defineProperty ، فإن تشغيل كود ES3 في بيئة ES5 ، سيواجه مشكلة القراءة فقط. لذلك نحتاج إلى خطأ في التحويل البرمجي للهدف es3
  • قم بتجميعها باستخدام Object.defineProperty() و writable: true للهدف التجميعي es5 وإصدار تحذير / خطأ يوضح أن استخدام أسماء الخصائص هذه يمكن أن يتسبب في حدوث أخطاء في المتصفحات x of version <= y اقتراح أنه إذا كان يجب دعم هذه المتصفحات ، فإن الخيار الأكثر أمانًا هو اختيار اسم آخر.
  • إذا كنت لا تريد مطلقًا أن يستخدم الأشخاص الخصائص ، فقم بإنشاء خطأ تجميع لأي هدف.

بغض النظر عن إخراج الترجمة ، أعتقد أن أي نوع من الرسائل الإضافية سيكون أفضل من الوضع الحالي (TS 1.8.10) حيث لا نحصل على أي تلميح على الإطلاق حول المشكلات المحتملة في إخراج المترجم.

تحرير : تمت إضافة القص

ال 22 كومينتر

واجهت هذا مؤخرًا. :(

أيضًا عدد قليل من الآخرين غير مسموح بهم ، على سبيل المثال ، يجب أن يكون الرمز التالي خطأ (إذا قمنا بهذه الميزة):

class C {
    static name = 'something';
    static arguments = 'args';
    static caller = 'caller';
}

console.log(C.name); // 'C'
console.log(C.arguments); // null
console.log(C.caller); // null

ومع ذلك ، ليست كل هذه الأشياء قياسية.

لا أعتقد أن الخصائص name و caller و length قابلة للتنفيذ. إنها خصائص للقراءة فقط ولا يمكن تجاوزها. سيتم تجاهل جميع التعيينات لهم.

tinganho وافق

حسنًا ، ولكن نظرًا لأن الأشخاص يكتشفون هذا النوع من الخطأ من وقت لآخر ، أعتقد أنه يجب على TS إخطارهم بفعل شيء خاطئ. لأن خصائص مثل name أو length من الطبيعي جدًا أن تضعها في الاعتبار ، لذا سيحاول الناس إعادة تعريفها مرارًا وتكرارًا.

قد يكون ذلك بسبب Lengh ، الاسم محدد بالفعل.

سأحاول وأعمل على هذا. بصرف النظر عما سبق ذكره ، هل هناك المزيد من أسماء العقارات التي لا ينبغي السماح بها؟

حتى الآن أرى:
الطول ، الاسم ، الحجج ، المتصل

ما الذي يجب أن يحدث بالضبط عندما يحاول شخص ما تعيين خاصية ثابتة بأحد الأسماء الممنوعة؟ خطأ المترجم؟ تحذير مرئي للمستخدم؟

أنا جديد على هذا ، لذا إذا فاتني شيء ما ، فسيكون هناك تقدير لبعض الإرشادات. : +1:

لماذا لا تجمع

class C {
    static name = 'something';
    static arguments = 'args';
    static caller = 'caller';
}

console.log(C.name); // 'C'
console.log(C.arguments); // null
console.log(C.caller); // null

إلى شيء مثل

var C = (function () {
    function C() {
    }

    C.__statics = {
        name: 'something',
        arguments: 'args',
        caller: 'caller'
    };

    return C;
})();
console.log(C.__statics.name); // 'something'
console.log(C.__statics.arguments); // 'args'
console.log(C.__statics.caller); // 'caller'

تم طرح السؤال على stackoverflow أيضًا: http://stackoverflow.com/a/34644236/390330 : ارتفع:

zerkms من فضلك لا تنشر نفس التعليق في مكانين ؛ انه مربك.

لا يمكنك في بعض الأحيان إعادة كتابة الأسماء بشكل تعسفي في نظام كتابة هيكلي.

ضع في اعتبارك بعض التعليمات البرمجية مثل هذا

interface HasName {
  name: string;
}
class Foo {
  static name = 'fooClass';
}
let bar: HasName = { name: string };
let q = Math.random() > 0.5 ? Foo : bar;
console.log(q.name);

RyanCavanaugh هذا مثال عادل ، بالفعل (أنا لا أطور على TS ، لكن يا إلهي - نظام نوعه غريب بمجرد أن يتعامل مع هذا الرمز على أنه صالح)

إذا لم يكن من الممكن تحويلها دون مخاطرة ، فربما يجب علينا فقط عدم السماح بها؟

إذا لم يكن من الممكن تحويلها دون مخاطرة ، فربما يجب علينا فقط عدم السماح بها؟

بالتأكيد عدم تغيير التحويل ، فقط جعله خطأ تجميع: روز:

[...] ربما علينا فقط عدم السماح لهم؟

بعض المطورين المغامرين يجب أن يرسلوا لنا العلاقات العامة! :غمزة:

لماذا لا تستخدم Object.defineProperty ؟

على سبيل المثال

class C {
    static length() { return "twelve"; }
}

سيتم نقلها إلى شيء مثل

var C = (function () {
    function C() {
    }
    Object.defineProperty(C, "length", {
        value: function () { return "twelve"; },
        writable: true
    });
    return C;
}());

@ nicolo-ribaudo هذا بالفعل يعمل. رأيي: لكنني أفضل رؤية خطأ بدلاً من مثل هذا التحويل. يميل TypeScript عمومًا إلى جانب الخطأ الرشيق بدلاً من _ إصلاح JavaScript_: rose:

يميل TypeScript عمومًا إلى جانب الخطأ الرشيق بدلاً من إصلاح JavaScript

ليست الفكرة الكاملة لـ TS هي إصلاح JS عن طريق سد الثغرات التي لا يمكن ولن تكون قادرة على الإطلاق.

ليست الفكرة الكاملة لـ TS هي إصلاح JS عن طريق سد الثغرات التي لا يمكن ولن تكون قادرة على الإطلاق.

نعم. ولكن من خلال فهم كيفية عمل JavaScript. خذ مثالاً على null و undefined . اختارت TypeScript أن تفهم كليهما (بدلاً من دمجها في شيء واحد مثلما يفعل Dart https://www.dartlang.org/docs/synonyms/). يعطي TypeScript أخطاء (بدلاً من إصلاحه في transpile) إذا كنت تستخدم نمط JavaScript خاطئ: rose:

آرائي خاصة بي ولم يقرها أحد سواي: روز:

وفي الوقت نفسه ، وصل الدعم الأصلي ES6 / 2015 إلى Chrome و Firefox. إذا لاحظنا كيف يتعامل هؤلاء مع المشكلة في الأصل ، فسيكون قريبًا مما اقترحه @ nicolo-ribaudo وأنا (انظر # 9778)

مقتطف لتوضيح السلوك الأصلي:

class Foo {
    constructor() {}
}
class Bar {
    static length() {}
    static name() {}
    static caller() {}
}
Foo.name = "FooChanged";
Bar.name = "Baz";

console.log(Foo.name) // Logs "Foo". Foo.name remains unwritable
console.log(Bar.name) // Logs "Baz".  Bar.name became writable

فيما يتعلق بما كتبه tinganho سابقًا عن القراءة فقط لـ name و length و caller يمكننا ملاحظة أن الخصائص قابلة للكتابة على دالة المُنشئ مرة واحدة لقد حددنا أيًا من هؤلاء على أنه عضو في فئة ثابتة (لا تتردد في مراجعة أو تعديل تحذيراتي الأخيرة على MDN فيما يتعلق بالافتراضات الخطيرة حول Function.name للحصول على اسم فئة ، بسبب هذا).

لذا فإن استخدام Object.defineProperty كما اقترحه @ nicolo-ribaudo سيحاكي السلوك المحلي بدقة. الشيء الذي يجب مراعاته هو أن بعض إصدارات المستعرضات الأقدم ولكن المتوافقة مع ES5 قد حددت الخصائص لتكون configurable: false . لذا فإن محاولة جعلهم writable: true ستفشل بالنسبة لهم (على سبيل المثال ، انظر قابلية تكوين Function.name )

لتلخيص الأمور ، كان رأيي في هذه القضية:

  • لا يمكننا استخدام Object.defineProperty() للهدف التجميعي es3 . بدون Object.defineProperty ، فإن تشغيل كود ES3 في بيئة ES5 ، سيواجه مشكلة القراءة فقط. لذلك نحتاج إلى خطأ في التحويل البرمجي للهدف es3
  • قم بتجميعها باستخدام Object.defineProperty() و writable: true للهدف التجميعي es5 وإصدار تحذير / خطأ يوضح أن استخدام أسماء الخصائص هذه يمكن أن يتسبب في حدوث أخطاء في المتصفحات x of version <= y اقتراح أنه إذا كان يجب دعم هذه المتصفحات ، فإن الخيار الأكثر أمانًا هو اختيار اسم آخر.
  • إذا كنت لا تريد مطلقًا أن يستخدم الأشخاص الخصائص ، فقم بإنشاء خطأ تجميع لأي هدف.

بغض النظر عن إخراج الترجمة ، أعتقد أن أي نوع من الرسائل الإضافية سيكون أفضل من الوضع الحالي (TS 1.8.10) حيث لا نحصل على أي تلميح على الإطلاق حول المشكلات المحتملة في إخراج المترجم.

تحرير : تمت إضافة القص

RyanCavanaugh : هل يمكنك رجاءً إعادة النظر في هذه المشكلة للاطلاع على معلم TS 2.0.1. يبدو الحل واضحًا للأمام ولكن اعتمادًا على الخيار الذي تختاره قد يحتاج إخراج المرسل إلى التغيير (انظر تعليقي السابق). قد يكون من الأفضل عندئذٍ إصدار TS 2.0 لتضمين الإصلاح.

تشير العلامات الموجودة في العلاقات العامة إلى أن فريق TypeScript ، الذي لديه موارد محدودة ، يترك هذا مفتوحًا أمام المجتمع للتعامل معه. إذا كنت تريد معالجة هذه المشكلة ، فسيتعين على شخص ما في المجتمع الأوسع معالجتها حتى يشعر فريق TypeScript الأساسي أن لديهم مساحة كافية في الأعمال المتراكمة لوضعها في إصدار (والذي من المحتمل أن يكون لفترة طويلة).

kitsonk شكرًا لك على شرح تسمية العلاقات العامة. أعتقد أنني فهمت ذلك. ما اقترحته هو إعادة تقييم ما إذا كانت لا تزال الطريقة الصحيحة للتعامل مع المشكلة. من غير المحتمل أن تحدث خصائص الفئة الثابتة المسماة _name_ أو _length_ ، وينتج TS ناتجًا خاطئًا لذلك. ومن ثم لن أسمي القضية و "حالة الحافة".

أنا أعتبر أن الخصائص الثابتة هي جوهر اللغة وحتى إذا لم تكن هناك طلبات سحب حتى الآن ، فقد تم تقديم حلول للمشكلة في هذا الموضوع.

ومع ذلك ، سوف أقوم بتقييم ما إذا كان بإمكاني تقديم العلاقات العامة ولكن يجب أن أعترف أنني لست على دراية بمصادر TS وأخشى أن يتم إصدار TS 2.0 من قبل.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات