أنواع بأسلوب Result/Either
مثّل النجاح والفشل صراحةً باستخدام اتحاد Result/Either، وأضف دوالًا مساعدة مثل map وflatMap وmapError، وحافظ على قابلية توقّع التدفقات من دون استخدام try/catch في كل موضع.
أنواع بأسلوب Result/Either درس مجاني في TypeScript Academy على CoddyKit. هذا هو الدرس 1 من أصل 2. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في TypeScript Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة TypeScript Academy 2 دروس في المجموع.
مقدمة
الهدف: اجعل حالات الفشل مرئية. ستنمذج النتائج باستخدام اتحاد مميّز، وتركّب العمليات باستخدام مساعدين، وتحول الاستثناءات عند الحدود.
- نوع Result
- map/flatMap/mapError
- تكامل HTTP
أساس Result
أنشئ أداة صغيرة من نوع Result: منشئات ok/err، بالإضافة إلى map وflatMap وmapError للتركيب.
export type Ok<T> = { ok: true; value: T }
export type Err<E> = { ok: false; error: E }
export type Result<T, E> = Ok<T> | Err<E>
export const ok = <T>(value: T): Ok<T> => ({ ok: true, value })
export const err = <E>(error: E): Err<E> => ({ ok: false, error })
export function map<T, E, U>(r: Result<T, E>, f: (t: T) => U): Result<U, E> {
return r.ok ? ok(f(r.value)) : r
}
export function flatMap<T, E, U>(r: Result<T, E>, f: (t: T) => Result<U, E>): Result<U, E> {
return r.ok ? f(r.value) : r
}
export function mapError<T, E, F>(r: Result<T, E>, g: (e: E) => F): Result<T, F> {
return r.ok ? r : err(g(r.error))
}أخطاء المجال
نمذج أخطاء المجال على هيئة اتحاد مميّز مع وسم tag. ويحمل كل فرع بيانات دقيقة لإنتاج رسائل جيدة.
export type CreateUserError =
| { tag: "InvalidEmail"; detail?: string }
| { tag: "Duplicate"; email: string }
export function validateEmail(email: string): Result<string, CreateUserError> {
const okEmail = /.+@.+/.test(email)
return okEmail ? ok(email.toLowerCase()) : err({ tag: "InvalidEmail", detail: "bad format" })
}
const existing = new Set(["ada@example.com"]) // pretend DB
export function saveUser(email: string): Result<{ id: string }, CreateUserError> {
if (existing.has(email)) return err({ tag: "Duplicate", email })
return ok({ id: Math.random().toString(36).slice(2) })
}تركيب التدفقات
ركّب عمليات التحقق باستخدام flatMap. استخدم switch مع فحص never لفرض الشمولية في وقت الترجمة.
export function createUser(flowEmail: string) {
return flatMap(validateEmail(flowEmail), email => saveUser(email))
}
// Use
const r = createUser("Ada@example.com")
if (r.ok) {
console.log("id:", r.value.id)
} else {
switch (r.error.tag) {
case "InvalidEmail": console.error("invalid email:", r.error.detail); break
case "Duplicate": console.error("already used:", r.error.email); break
default: ((x: never) => x)(r.error) // exhaustiveness
}
}الاستثناء → Result
عند حدود عمليات الإدخال والإخراج، غلّف الاستثناءات وحوّلها إلى Result. وبذلك يتعامل المستدعون مع مسار أخطاء واحد.
export async function fromPromise<T>(p: Promise<T>): Promise<Result<T, { tag: "Exception"; message: string }>> {
try { return ok(await p) }
catch (e) { return err({ tag: "Exception", message: e instanceof Error ? e.message : String(e) }) }
}
// Example: wrap a fetch
export async function fetchJson<T>(url: string): Promise<Result<T, { tag: "Exception"; message: string }>> {
return fromPromise(fetch(url).then(r => r.json() as T))
}نصائح تعيين HTTP
تكامل HTTP: عيّن أخطاء المجال إلى 400/409، واستثناءات الإدخال والإخراج إلى 502/503. أبقِ دالة التعيين صغيرة لكي تظل المتحكمات نظيفة وقابلة للتنبؤ.
التحقق من فائدة Result
تحقق سريع: لماذا نفضّل اتحاد Result المميّز؟
خلاصة
خلاصة: عرّف نوع Result صغيرًا، وركّب العمليات باستخدام map/flatMap، ونمذج أخطاء المجال كاتحادات، وحوّل الاستثناءات عند الحدود.
الأسئلة الشائعة
هل درس «أنواع بأسلوب Result/Either» مجاني؟
نعم — نص درس «أنواع بأسلوب Result/Either» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة TypeScript Academy، انتقل إلى CoddyKit PRO. تتضمن دورة TypeScript Academy 2 دروس في المجموع.
ماذا ستتعلم في «أنواع بأسلوب Result/Either»؟
مثّل النجاح والفشل صراحةً باستخدام اتحاد Result/Either، وأضف دوالًا مساعدة مثل map وflatMap وmapError، وحافظ على قابلية توقّع التدفقات من دون استخدام try/catch في كل موضع. تتمرن على TypeScript Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ TypeScript Academy؟
لا تُشترط خبرة سابقة. TypeScript Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 1 من أصل 2.
كم من الوقت يستغرق درس «أنواع بأسلوب Result/Either»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس TypeScript Academy هذا؟
نعم. كل درس في TypeScript Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- أنواع بأسلوب Result/Either
- معالجة الأخطاء الشاملة باستخدام الاتحادات المميّزة