افهم حلّ التحميلات الزائدة، والبارامتر الزائف this، وقواعد التغايرية التي تحكم قابلية إسناد الدوال.
افتح هذا الدرس في Kodokonالدالّة ذات التحميل الزائد تكشف قائمة من التواقيع العامّة يتبعها توقيع تنفيذ واحد. نقطة أساسية في المواصفات: هذا الأخير غير مرئي من الخارج؛ فلا يمكن استدعاء سوى التحميلات المُصرَّح بها. يمرّ الحلّ على التواقيع من الأعلى إلى الأسفل ويحتفظ بأول توقيع متوافق: ضَع دائماً التوقيع الأكثر تخصيصاً أولاً، وإلا فلن يُختار أبداً.
function parse(input: string): number;
function parse(input: string[]): number[];
function parse(input: string | string[]) {
return Array.isArray(input)
? input.map((s) => s.length)
: input.length;
}
const single = parse("abc"); // number
const many = parse(["a", "bb"]); // number[]يُتيح لك TypeScript التصريح ببارامتر زائف this في الموضع الأول. وهو مَحذوف بالكامل من الجافاسكريبت المُنتَجة: إنه قيد ساكن محض على سياق الاستدعاء، يُفحَص عند تفعيل noImplicitThis. وتُتيح الأداتان ThisParameterType وOmitThisParameter استخراجه أو إزالته، وهذا جوهري لتصنيف الدوال المُعدّة للاستخدام مع call أو apply أو bind.
function greet(this: { name: string }, msg: string) {
return `${msg}, ${this.name}`;
}
type Ctx = ThisParameterType<typeof greet>;
// { name: string }
type Fn = OmitThisParameter<typeof greet>;
// (msg: string) => string
const user = { name: "Ada", greet };
user.greet("Hello"); // "Hello, Ada"
// greet("Hi"); // error: missing this contextتصف التغايرية كيف تنتشر قابلية الإسناد عبر باني نوع. بالنسبة إلى الدوال، تكون أنواع الإرجاع تغايرية مشتركة (covariant)، ومع strictFunctionTypes تكون البارامترات تغايرية معاكسة (contravariant): يمكن لدالّة تقبل نوعاً أوسع أن تحلّ محلّ دالّة تقبل نوعاً أضيق، لا العكس أبداً. استثناء مقصود واحد: تبقى بارامترات التوابع المُصرَّح بها بالصيغة المختصرة ثنائية التغاير (bivariant)، وهو تسوية تاريخية، لولاها لما كان Array<Dog> قابلاً للإسناد إلى Array<Animal>. ومنذ الإصدار 4.7، يمكنك التأشير على التغايرية المتوقَّعة بواسطة in وout، مثل interface Producer<out T>، ويتحقّق المُصرِّف منها.
interface Animal { name: string }
interface Dog extends Animal { bark(): void }
declare let f: (a: Dog) => void;
declare let g: (a: Animal) => void;
f = g; // OK: g accepts a wider type, that is safe
// g = f; // error with strictFunctionTypes
interface Sink { accept(a: Animal): void }
interface DogSink { accept(a: Dog): void }
declare let s: Sink;
declare let d: DogSink;
d = s; s = d; // both compile: bivariance!this الخاص بدالّة في الجافاسكريبت المُنتَجة؟