الورقة المرجعية Cheatsheet
للاسترجاع بعد الفهم لا للحفظ قبله
هذه ليست لتتعلّم منها؛ هي لتتذكّر بها ما اشتققته. كل سطرٍ هنا له "ليش" في إقليمٍ ما — إن لم تتذكّره، ارجع للإقليم لا للسطر.
الشبكة (الإقليم ٢)
| النوع | المجموعة | يُسنَد إليه | يُسنَد منه |
|---|---|---|---|
unknown | كل القيم (القمّة) | كل شيء | لا شيء (إلا unknown) |
never | ∅ (القاع) | لا شيء (إلا never) | كل شيء |
any | ليس مجموعة (ثقب) | كل شيء | كل شيء |
void | "تُجاهَل القيمة" | undefined (وأي عائدٍ يُهمَل) | — |
قاعدة: استبدل كل any بـ unknown، ثم ضيّق.
جبر المجموعات (الإقليم ٣)
typescriptA | B // اتحاد: قيمة في A أو B؛ عمليات A ∩ B فقط A & B // تقاطع: قيمة في A و B؛ كائنات أغنى string & number // = never "a" | "b" | "c" // مجموعة محدودة بالتعداد let x = 5 // → number (widening) const x = 5 // → 5 x = "n" as const // → "n" (أضيق + readonly)
التضييق (الإقليم ٤)
typescripttypeof x === "string" | "number" | "boolean" | "object" | ... if (x) {} // يطرح القيم الكاذبة x === "literal" // يثبت/يطرح حرفية "key" in obj // وجود خاصية x instanceof Class // عضوية صنف Array.isArray(x) // مصفوفة x == null // null و undefined معاً // discriminated union + exhaustiveness: switch (s.kind) { case "a": ... default: const _: never = s; // حارس الشمول } function isT(x: unknown): x is T { ... } // type predicate function assertT(x: unknown): asserts x is T { ... }
الكائنات (الإقليم ٥)
typescript{ x: number; y?: number } // y اختيارية = number | undefined { readonly x: number } // قيدٌ وقت الترجمة فقط (يُمحى!) { [k: string]: number } // index signature (قاموس) // excess property check: يضرب فقط على الكائنات الحرفية الطازجة
التباين (الإقليم ٦)
المعاملات → contravariant (الاستهلاك يقلب ⊆)
الإرجاع → covariant (الإنتاج يحفظ ⊆)
المصفوفات → covariant عمداً = ثقب (Dog[] حيث Animal[])
() => void يقبل أي عائد (covariance + مستهلك أعمى)
Generics (الإقليم ٧)
typescriptfunction id<T>(x: T): T { return x; } <T extends { length: number }> // قيد = T ⊆ C <T, K extends keyof T>(o: T, k: K): T[K] // keyof + indexed access type Box<T> = { value: T }; type Pair<A, B = A> = { first: A; second: B }; // افتراضي
البرمجة على الأنواع (الإقليم ٨)
typescriptT extends U ? X : Y // if (يوزّع على الاتحاد إن كان T عارياً) [T] extends [U] ? X : Y // تعطيل التوزيع T extends (...a: any[]) => infer R ? R : never // استخراج (infer) T extends (infer E)[] ? E : never T extends Promise<infer V> ? V : T { [K in keyof T]: T[K] } // mapped (حلقة) { readonly [K in keyof T]?: T[K] } // مع مُعدِّلات { -readonly [K in keyof T]-?: T[K] } // نزع المُعدِّلات { [K in keyof T as `get${Capitalize<string & K>}`]: ... } // key remap + template type Reverse<T extends any[]> = T extends [infer H, ...infer R] ? [...Reverse<R>, H] : []; // عودية
أدوات قياسية جاهزة (كلها مبنيّة ممّا سبق — اقرأ مصدرها): Partial<T>, Required<T>, Readonly<T>, Pick<T,K>, Omit<T,K>, Record<K,V>, Exclude<T,U>, Extract<T,U>, NonNullable<T>, ReturnType<F>, Parameters<F>, Awaited<T>.
الحواف ونقاط الثقة (الإقليم ٩)
typescriptx as T // ادّعاء بلا فحص (ليس cast — صفر أثر وقت التشغيل) x! // "ليست null" بلا فحص JSON.parse(s) // any → ادّعاء النوع كذبةٌ غير مفحوصة arr[i] // قد يكون undefined (فعّل noUncheckedIndexedAccess) // عبور الجدار الصحيح: const data: unknown = JSON.parse(raw); if (!isUser(data)) throw new Error("invalid"); data.id; // مفحوصٌ الآن // استعادة الاسمية: type Brand<T, B> = T & { readonly __brand: B }; type UserId = Brand<number, "UserId">;
tsconfig — الأعلام التي تهمّ
tsconfig.json{ "compilerOptions": { "strict": true, // إلزامي — يشمل strictNullChecks و strictFunctionTypes "noUncheckedIndexedAccess": true, // يغلق ثقب الفهرسة (خارج strict) "noImplicitAny": true, // ضمن strict "exactOptionalPropertyTypes": true // صرامة أعلى لـ ? } }
الأوامر
bashtsc --noEmit # افحص بلا إخراج JS tsc --watch # افحص مستمراً # أو جرّب فوراً: https://www.typescriptlang.org/play
مبدأ
القاعدة الذهبية فوق كل ما سبق: حين يرفض المترجم، اسأل "أي ادّعاءٍ رياضي يقول إنه كاذب؟" لا "كيف أُسكِته؟". المترجم يبرهن؛ افهم البرهان.
منهج TypeScript — من الجذور · نظرية مجموعات + مُبرهِن نظريات
النوع = مجموعة