Typealias هو إعلان في Swift ينشئ اسمًا بديلاً لنوع موجود دون تعريف نوع جديد. الاسم المستعار مكافئ تمامًا للنوع الأصلي في مرحلة الترجمة — يستبدل المترجم النوع الأصلي في كل مكان يُستخدم فيه typealias. وفقًا لدليل Swift Language Guide (2025)، يُستخدم typealias لتقصير التواقيع الطويلة، وتجريد الأنواع الداخلية عبر associatedtype في البروتوكولات وتبسيط معاملات generic المعقدة. على عكس غلاف النوع (wrapper)، لا يضيف typealias أمانًا للأنواع — إنه مجرد اسم مستعار لا يميزه نظام الأنواع.
النقاط الرئيسية
typealias NewName = ExistingType — يمكن التصريح به في أي مستوى (عام، محلي، داخل نوع)typealias Result = Swift.Result<Data, Error>typealias Handler = (Int) -> VoidTypealias هو إعلان في Swift يقدم اسمًا بديلاً لنوع موجود. بعد التصريح عن typealias، يمكن استخدام الاسم الجديد في أي مكان يُتوقع فيه النوع الأصلي — يعاملهما المترجم كمتطابقين. لا يضيف Typealias عزلًا دلاليًا: يمكن تمرير قيمة من نوع UserID (typealias لـ String) إلى دالة تنتظر String دون خطأ.
الأغراض الرئيسية لـ typealias هي تقصير الأسماء الطويلة، وتوثيق الغرض من النوع، وتجريد التنفيذ الملموس. على سبيل المثال، typealias JSON = [String: Any] يشير صراحةً إلى أن القاموس يُستخدم كهيكل JSON، و typealias Completion = (Result<Data, Error>) -> Void يحول توقيع closure معقدًا إلى نوع قابل للقراءة.
وفقًا لـ Swift.org (2025)، يُستخدم typealias على نطاق واسع في المكتبة القياسية. على سبيل المثال، String هو typealias لـ String (Array<Character> متخصص)، على الرغم من أن هذا التنفيذ مخفي في الإصدارات الحديثة من Swift. Void هو typealias للـ tuple الفارغ ()، مما يجعل تواقيع الدوال أكثر قابلية للقراءة.
استخدم typealias لتوثيق دلالات النوع، لكن تذكر: أنه لا يحمي من خلط مفاهيم مختلفة لنفس النوع الأساسي. للفصل الآمن للأنواع، استخدم الأغلفة (struct wrapper).
يتم التصريح عن Typealias بالكلمة المفتاحية typealias، متبوعة بالاسم الجديد، علامة يساوي، والنوع الموجود. الشكل الأساسي:
typealias Name = ExistingType
typealias UserID = Int
typealias JSONDictionary = [String: Any]
يتم تحديد نطاق typealias حسب مكان التصريح:
| المستوى | مثال | الرؤية |
|---|---|---|
| عام | typealias Name = String | الوحدة بأكملها (خاضعة للتحكم في الوصول) |
| داخل نوع | struct User { typealias ID = Int } | User.ID — يمكن الوصول إليه عبر النوع |
| داخل دالة | func f() { typealias Local = Int } | فقط داخل الدالة |
| داخل بروتوكول | protocol P { associatedtype T } | يتم تحديده عند الاعتماد |
Typealias داخل نوع (على سبيل المثال، User.ID) هو نمط شائع لتجميع الأسماء المستعارة ذات الصلة. هذا يحسن الفضاءات الاسمية: Order.ID و User.ID كلاهما Int، لكن يُقرآن كمفهومين مختلفين. يتم الوصول إلى typealias المتداخل عبر User.ID أو عبر تدوين النقطة إذا كان النوع معروفًا.
أحد أكثر استخدامات typealias شيوعًا هو تبسيط تواقيع closure. يمكن أن تكون أنواع closure في Swift مرهقة، خاصةً مع Optional والمعاملات العامة. Typealias يحول (Data?, Error?) -> Void إلى FetchResultHandler قابل للقراءة:
typealias FetchResultHandler = (Data?, Error?) -> Void
func fetchUser(id: Int, completion: FetchResultHandler) {
// network request
completion(data, nil)
}
وفقًا لدليل أسلوب Ray Wenderlich، فإن typealias للـ closures يحسن readability لتواقيع الدوال، خاصةً في بروتوكولات التفويض وأنماط الاستدعاء. ومع ذلك، تجنب الإفراط في الأسماء المستعارة — إذا تم استخدام closure في مكان واحد، يمكن التصريح به inline.
تستخدم المكتبة القياسية لـ Swift هذا الأسلوب بنشاط. على سبيل المثال، DispatchQueue.WorkItem هو typealias لـ DispatchWorkItem، على الرغم من أنه يبدو من الخارج كنوع منفصل. Typealias للـ closures هو أداة readability — لا تفرط في استخدامها: 3–5 أسماء مستعارة للـ closures لكل وحدة هو حد معقول.
يمكن أن يتضمن Typealias معاملات عامة (generic)، مما ينشئ إصدارات متخصصة من الأنواع العامة. هذا مفيد بشكل خاص عند العمل مع Result و Publisher وأنواع عامة أخرى من المكتبة القياسية و Combine:
typealias FetchResult = Result<Data, Error>
typealias AnyPublisherOfData = AnyPublisher<Data, Error>
func loadData() -> FetchResult {
// data loading
}
يمكنك أيضًا إنشاء typealias بمعاملات عامة مخصصة يتم توجيهها إلى النوع الأصلي:
typealias NetworkResult<T> = Result<T, NetworkError>
func fetchUser() -> NetworkResult<User> {
// ...
}
قاعدة مهمة: لا يمكن لـ typealias إضافة قيود عامة جديدة (where clauses) — إنه فقط يوجه المعاملات إلى النوع الأصلي. إذا كانت هناك حاجة لقيود إضافية، قم بإنشاء struct أو class عام. وفقًا لـ Swift by Sundell (2024)، فإن typealias مع الـ generics هو طريقة مثالية لتقصير التواقيع المتكررة في المشاريع التي تستخدم Combine و Result و async/await بكثافة.
Associatedtype هو typealias تم التصريح عنه داخل بروتوكول يحدد نوعًا مرتبطًا. على عكس typealias العادي، لا يرتبط associatedtype بنوع محدد في وقت التصريح — يتم تحديده بواسطة كل نوع يعتمد البروتوكول:
protocol Container {
associatedtype Item
var count: Int { get }
mutating func append(_ item: Item)
}
struct IntBox: Container {
typealias Item = Int
// implementation
}
struct StringBox: Container {
typealias Item = String
// implementation
}
يعطي Associatedtype للبروتوكولات مرونة الأنواع العامة دون تحديد نوع ملموس في مكان التصريح. هذا هو أساس العديد من أنماط Swift: Collection (Element)، IteratorProtocol (Element)، Identifiable (ID). يمكن للمترجم استنتاج associatedtype تلقائيًا من التنفيذ، لذلك غالبًا ما يتم حذف typealias Item = Int الصريح — يستنتج Swift Item كـ Int من معامل الدالة append.
وفقًا لـ Swift Evolution SE-0195 (2022)، تم تقديم أنواع النتائج الغامضة (some Container) للعمل مع البروتوكولات التي تحتوي على associatedtype — مما حل مشكلة PAT (البروتوكولات ذات الأنواع المرتبطة)، والتي كانت تمنع استخدام هذه البروتوكولات كأنواع متغيرات.
الفرق الرئيسي: typealias هو مجرد اسم آخر لنوع موجود، بينما الغلاف (wrapper) هو نوع جديد، معزول دلاليًا عن الأصل. إذا أعلنت typealias UserID = Int، فإن UserID و Int قابلان للتبادل — دالة تنتظر Int ستقبل UserID دون خطأ.
يتم إنشاء الغلاف عبر struct ويوفر أمانًا حقيقيًا للأنواع:
struct UserID: RawRepresentable {
let rawValue: Int
}
struct OrderID: RawRepresentable {
let rawValue: Int
}
// Compilation error: cannot pass OrderID where UserID is expected
وفقًا لـ Point-Free (2025)، الأغلفة مفضلة عندما يتم تمثيل مفاهيم مختلفة بنفس النوع الأساسي (UserID مقابل OrderID). Typealias مبرر عندما يكون الهدف هو readability دون عزل: تقصير الأسماء الطويلة، توثيق الدلالات، تجريد التنفيذ عبر associatedtype. اختر typealias لسهولة القراءة، والغلاف لأمان الأنواع.
الأسئلة الشائعة
Typealias هو اسم مستعار لنوع موجود محدد. Associatedtype يتم التصريح عنه داخل بروتوكول ويتم تحديده بواسطة كل نوع يعتمد البروتوكول — أنواع مختلفة يمكنها استخدام associatedtype مختلف لنفس البروتوكول.
لا، typealias هو مجرد اسم بديل. المترجم يستبدله بالنوع الأصلي في وقت الترجمة. لإنشاء نوع جديد ومعزول دلاليًا، استخدم struct wrapper أو enum مع rawValue.
نعم، يمكن أن يتضمن typealias معاملات عامة: typealias Result<T> = Swift.Result<T, Error>. يتم توجيه المعاملات العامة إلى النوع الأصلي. لا يمكن إضافة قيود where — استخدم struct عامًا لذلك.
في أي مستوى: عام (في ملف)، داخل نوع (struct/class/enum)، داخل دالة، داخل بروتوكول (كـ associatedtype). يتم تحديد النطاق بمكان التصريح — typealias العامة مرئية في جميع أنحاء الوحدة، المحلية فقط داخل نطاقها.
اختر typealias لتقصير الأسماء الطويلة وتوثيق الدلالات عندما يكون التبادل مع النوع الأصلي آمنًا. اختر غلافًا (struct) عندما تحتاج إلى منع الخلط العرضي لمفاهيم مختلفة لنفس النوع الأساسي: UserID مقابل ProductID.
الخلاصة
typealias NewName = ExistingType، النطاقات — عام، داخل نوع، داخل دالةtypealias Handler = (Int) -> Voidسنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.