Typescript: اقتراح: النوع الأولي "الكائن"

تم إنشاؤها على ٢٦ يناير ٢٠١٥  ·  17تعليقات  ·  مصدر: microsoft/TypeScript

النوع الأساسي object

يصف هذا الاقتراح نوعًا أوليًا جديدًا للطباعة على الكتابة object .

حالة الاستخدام

تحتوي JavaScript core api على بعض الوظائف التي تأخذ object كمعامل:

  • Object.getPrototypeOf
  • Object.getOwnPropertyDescriptor
  • Object.create
  • ...إلخ

لا توجد حاليًا طريقة في الكتابة المطبوعة لمنع تمرير النوع الأولي الآخر ( string ، number ، إلخ ...) إلى تلك الوظائف.
على سبيل المثال ، Object.create('string') عبارة عن نص مكتوب صالح تمامًا ، حتى لو انتهى بخطأ.
سيسمح إنشاء نوع بدائي object بنمذجة توقيع هذه الوظيفة بشكل أكثر دقة ، وكل دالة تشترك في قيد مماثل.

اكتب فحص

الاحالة

النوع object يعادل {} مطروحًا منه قابلية التخصيص للنوع الأساسي الآخر ، وهذا يعني أن:

  • أي أنواع أساسية أخرى غير قابلة للتخصيص إلى object
  • يمكن object أي نوع غير أساسي إلى
  • الكائن قابل للتخصيص فقط لـ {} و any

هذا السلوك متناسق مع طريقة عمل جافا سكريبت ، فالنوع يمثل كل قيمة تحترم القيد typeof value === 'object' plus undefined .

اكتب الحارس

يجب تقديم نوع جديد من الحراس مقابل object : typeof value === 'object' .
اختياريًا ، يمكن للمترجم أيضًا قبول المقارنة مع وظيفة المصبوب Object : Object(value) === value .

Suggestion help wanted

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

+1 على هذا الاقتراح. لن أعتبر أن WeakMap واجهة برمجة تطبيقات "خبير" ، لكنني أعتبرها سببًا كافيًا لتنفيذ ذلك. نظرًا لأن وقت التشغيل يميز بين أنواع الكائنات والأنواع الأولية ، فمن المنطقي أن يكون لديك ميزة في TypeScript لتمييزها أيضًا.

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

ال 17 كومينتر

سيكون من المفيد سرد بعض واجهات برمجة التطبيقات بخلاف وظائف Object. التي ستستفيد من ذلك.

في javascript core api باستثناء Object ربما ستستفيد بعض بنيات es6 من هذا (WeakMap ، Proxy إلخ).
ولكن على سبيل المثال ، ستكتسب كل وظيفة مجموعات شرطة null ، ImmutableJS ، Mori إلخ.

تحرير: تعمل مجموعة التسطير السفلي مع أي نوع

نوقشت في اجتماع مراجعة الاقتراح. كل هذا منطقي ، لكننا بحاجة إلى تبرير تعقيد النوع البدائي الجديد بعدد الأخطاء / ثراء الوصف الذي يمكنه توفيره. بشكل أساسي ، المزيد من الأمثلة على واجهات برمجة التطبيقات التي لا يمكنها العمل على الأساسيات ، خاصة تلك التي ليست "خبيرة" لواجهات برمجة التطبيقات (مثل الوكلاء)

نشر كمرجع أكثر من توصية: غمزة:

interface String { _primitiveBrand?: string; }
interface Boolean { _primitiveBrand?: boolean; }
interface Number { _primitiveBrand?: number; }

interface ObjectOnly {  _primitiveBrand?: void; }

function fn(x: ObjectOnly) { }

// Error
fn(43);
// Error
fn('foo');
// OK
fn({});
// OK
fn(window);

+1 على هذا الاقتراح. لن أعتبر أن WeakMap واجهة برمجة تطبيقات "خبير" ، لكنني أعتبرها سببًا كافيًا لتنفيذ ذلك. نظرًا لأن وقت التشغيل يميز بين أنواع الكائنات والأنواع الأولية ، فمن المنطقي أن يكون لديك ميزة في TypeScript لتمييزها أيضًا.

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

يتطلب Object.observe هدفًا غير بدائي أيضًا: http://arv.github.io/ecmascript-object-observe/#Object.observe

أعتقد أن العنوان مربك بعض الشيء لأنه يذكر كلمة "بدائي". يمكن بدلاً من ذلك تسمية _ "نوع كائن ECMAScript" _ أو _ "نوع كائن وقت التشغيل" _. والتي يمكن تخصيصها من أي شيء آخر غير الأنواع الأولية (بما في ذلك النوع والرموز undefined ) أو أنواع الوظائف أو المُنشئ. يجب أن تستند معايير نوع object القانوني إلى الحارس التالي:

let isObject (x) => typeof x === "object";

وفقًا لـ MDN ، هذا هو ناتج typeof :

غير محدد : "غير محدد"
لاغية : "كائن" (انظر أدناه)
منطقي : "منطقي"
الرقم : "number"
سلسلة : "سلسلة"
الرمز (جديد في ECMAScript 2015) : "الرمز"
الكائن المضيف (توفره بيئة JS) : يعتمد على التنفيذ
كائن الوظيفة (يطبق [[استدعاء]] بمصطلحات ECMA-262 : "function"
أي كائن آخر : "كائن"

بدون هذا النوع ، لا توجد طريقة لمطابقة نوع دقيق للحارس المذكور أعلاه بشكل صحيح ، ولا حتى كحارس معرف من قبل المستخدم. وهذا أمر ضروري للاستخدام مع أي وظيفة أيضا يتطلب بدقة كائن له خصائص ويسمح for in الحلقات والمكالمات إلى Object النموذج، ولتنفيذ القيود عامة مثل T extends object ثم الرجوع إلى الخصائص بأمان أو استخدام وظائف النموذج الأولي.

ومع ذلك ، فإن استبعاد الدوال والمنشئات سيكون محدودًا بعض الشيء في بعض الحالات ، لذلك قد يكون هناك نوع آخر من شأنه أن يشملهم أيضًا ويسمى _ ​​"نوع الكائن غير البدائي" _. قد يكون الحل الجزئي هو الاتحاد object | Function الرغم من الحاجة إلى استخدام القوالب أو الحراس الإضافيين للتعامل معه بشكل صحيح.

قبول العلاقات العامة. ويبدو أن هذا مشكلة شائعة؛ سيكون هذا تغييرًا جذريًا لأي شخص شجاع بما يكفي لكتابة interface object { ... } . يجب أن يكون التنفيذ مباشرًا ويتبع القواعد الموضحة أعلاه.

ملاحظة جانبية: نحن جميعًا نتساءل أين كان fdecampredon !

RyanCavanaugh تغيير مدينة العمل ، وللأسف ليس هناك الكثير من الكتابة المطبوعة في وظيفتي الجديدة: D

عظيم. أريد استخدام هذا النوع في TS1.8.

أود أيضًا أن أرى شيئًا مثل نوع object . ومع ذلك ، أتساءل عما إذا كان يجب أن يتوافق مع typeof value === 'object' ، لأن هذا قد يستبعد الوظائف. بدلاً من ذلك ، يبدو لي أن النوع المرتقب object يجب أن يعكس نوع لغة الكائن ، الذي يتضمن الوظائف. هناك عدة أسباب لذلك:

  • واجهات برمجة التطبيقات التي تقبل الكائنات العادية دائمًا ، على حد علمي ، تقبل أيضًا الوظائف.
  • ترث الدوال من المُنشئ Object .

سآخذ هذه بالترتيب.

واجهات برمجة التطبيقات

تقبل واجهات برمجة التطبيقات مثل WeakMap التي تأخذ الكائنات فقط نوع لغة الكائن ، وليس الكائنات العادية فقط. ما يلي مقبول:

function theAnswer() {}

let map = new WeakMap();

map.set(theAnswer, 42);
console.log(map.get(theAnswer)); // 42

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

ميراث

نظرًا لأن Function يوسع المُنشئ Object ، يمكننا استخدام الأساليب الثابتة والمثيلات المتاحة في Object على الوظائف أيضًا. على سبيل المثال ، ما يلي ممكن:

class DeepThought {
  static getAnswer() {
    return 42;
  }
}

let computer = Object.create(DeepThought);

console.log(computer.getAnswer()); // 42
console.log(Object.getPrototypeOf(computer)); // [Function: DeepThought]

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

لذا أود أن أقترح أن النوع object يتوافق مع ما يلي ، والذي يتوافق مع نوع لغة الكائن (باستثناء أنها تتضمن null ، لكن لا يوجد أي حماية ضد null في TypeScript على كل حال).

function isObject(value) {
  return typeof value === 'object' || typeof value === 'function';
}

حالة الاستخدام

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

interface NonPrimitive {
  [key: string]: any;
  [index: number]: any;
}

export class DeepMap {
  // ...
  private mapObject(obj: NonPrimitive): NonPrimitive { /* ... */ }
}

هذه ليست المرة الأولى التي أضطر فيها إلى تحديد واجهة NonPrimitive . سيكون من الرائع أن أفعل هذا:

export class DeepMap {
  // ...
  private mapObject(obj: object): object { /* ... */ }
}

كما اقترحت أعلاه ، لا يهمني حقًا ما إذا كانت المعلمة obj قابلة للاستدعاء أم لا. كل ما يهم هو أنه من النوع Object _language_ ، أي أنه مجموعة من الخصائص التي يمكنني تكرار أزواج القيمة الرئيسية من خلالها.

أوافق على أن الوظائف هي object s. القصد هو استبعاد الأوليات.

حسنًا ، اعتقدت أن هذا كان القصد. لقد ظننت أنني ربما أفتقد شيئًا مع كل هذا الحديث عن typeof value === 'object' .

هل سيسمح هذا النوع object بتعيين خاصية مخصصة (مثل any )؟ فمثلا:

const foo: object = {};

foo.bar = 'baz';

لا

ما هو الفرق العملي بين

export class DeepMap {
  // ...
  private mapObject(obj: object): object { /* ... */ }
}

و

export class DeepMap {
  // ...
  private mapObject(obj: Object): Object { /* ... */ }
}

؟ (باستخدام object مقابل Object ). يبدو لي أن Function يمتد من Object ، لذلك لا أرى سبب عدم قدرتنا على القيام بذلك بالفعل. هل يمكن ان توضح؟

trusktr جميع القيم بخلاف null و undefined يمكن تخصيصها للنوع Object ؛ الدالة التي تقبل Object ستتخذ سلسلة أو رقمًا أو منطقيًا أو رمزًا. يتم object القيم غير الأولية فقط إلى object مفيدًا حيث نتوقع قيمة غير أولية ، ولكن عندما لا نهتم بماهية خصائصه.

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