Typealias — คืออะไร ไวยากรณ์ และการใช้งานใน Kotlin

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-06-23 เวลาอ่าน: 7 นาที

Typealias เป็นกลไก Kotlin สำหรับสร้างชื่อทางเลือกสำหรับชนิดที่มีอยู่แล้ว คำสำคัญ typealias ช่วยให้คุณแทนที่การประกาศชนิดที่ซับซ้อนด้วยนามแฝงที่สั้นและชัดเจนโดยไม่ต้องสร้างชนิดใหม่ ตาม เอกสาร Kotlin (2026) typealias ช่วยปรับปรุงการอ่านโค้ด โดยเฉพาะในลายเซ็นเชอร์ของฟังก์ชันที่มีชนิดฟังก์ชัน Typealias ทำให้โค้ดสามารถอธิบายตัวเองได้โดยการแทนที่การประกาศที่ยาวเอือด้วยชนิดที่มีชื่อชัดเจน

ข้อเรียนรู้สำคัญ

  • Typealias — นามแฝงสำหรับชนิดที่มีอยู่แล้ว ไม่สร้างชนิดใหม่
  • ชนิดฟังก์ชัน — typealias แทนที่ (T) -> R ที่ซับซ้อนด้วยชื่อที่อ่านง่ายเช่น Callback
  • Generics — typealias รองรับพารามิเตอร์ทั่วไป: typealias ListMapper = (T) -> T
  • คลาสซ้อนกัน — typealias ย่อการเข้าถึงคลาสที่ซ้อนกันจากแพ็คเกจอื่น
  • ความปลอดภัยของชนิด — typealias ไม่เพิ่มการตรวจสอบขณะแปลง; นามแฝงสามารถแลกเปลี่ยนกับต้นฉบับได้อย่างสมบูรณ์

Typealias คืออะไร?

Typealias (นามแฝงชนิด) เป็นการประกาศที่แนะนำชื่อทางเลือกสำหรับชนิดที่มีอยู่แล้ว ไวยากรณ์: typealias ชื่อใหม่ = ชนิดที่มีอยู่ หลังจากการประกาศ สามารถใช้ชื่อใหม่ได้ทุกที่ที่คาดหวังชนิดที่มีอยู่ — คอมไพเลอร์ถือว่าเป็นชนิดเดียวกัน ในระดับไบต์โค้ด typealias ไม่ทิ้งรอยเว้น: ข้อมูลนามแฝงทั้งหมดจะถูกลบในขณะแปลง

จุดประสงค์หลักของ typealias คือการปรับปรุง การอ่านโค้ด แทนที่จะใช้ลายเซ็นเชอร์ยาว fun process(callback: (Result) -> Unit) คุณสามารถเขียน typealias Callback = (Result) -> Unit และใช้ Callback เป็นชนิดพารามิเตอร์ ซึ่งมีประโยชน์โดยเฉพาะเมื่อชนิดฟังก์ชันเดียวกันถูกทำซ้ำในหลายจุดในโค้ด: นามแฝงทำหน้าที่เป็นจุดกำหนดเดียวและบันทึกวัตถุประสงค์ของชนิด

Typealias ไม่สร้างชนิดใหม่ — เป็น เพียงคำพ้อง ตัวแปรชนิด Callback และ (Result) -> Unit สามารถแลกเปลี่ยนกันได้อย่างสมบูรณ์ คอมไพเลอร์จะไม่สร้างข้อผิดพลาดหากมอบ lambda โดยตรงไปยังฟังก์ชันที่คาดหวัง Callback ทำให้ typealias แตกต่างจาก inline class (value class) ซึ่งสร้างชนิดห่อหุ้มใหม่พร้อมการตรวจสอบขณะแปลง Typealias คือการตั้งชื่อใหม่ ไม่ใช่การห่อหุ้ม

Typealias สำหรับชนิดฟังก์ชัน

กรณีใช้งานที่พบบ่อยที่สุดของ typealias ใน Kotlin คือ ชนิดฟังก์ชัน ลายเซ็นเชอร์ยาวเช่น (Int, String) -> Boolean หรือ (List) -> Result ทำให้โค้ดอ่านยาก Typealias เปลี่ยนพวกมันเป็นชื่อสั้นที่มีความหมายซึ่งบันทึกวัตถุประสงค์ของฟังก์ชัน: typealias Validator = (String) -> Boolean ระบุว่านี่คือตัวตรวจสอบสตริง

kotlin
// Without typealias
fun findUsers(
    filter: (List<User>) -> List<User>
): List<User>

// With typealias
typealias UserFilter = (List<User>) -> List<User>

fun findUsers(filter: UserFilter): List<User>

// Usage in class
typealias OnClickListener = (View) -> Unit

class Button {
    var onClick: OnClickListener = {}
}

ในตัวอย่าง typealias UserFilter ซ่อนชนิดฟังก์ชันที่ซับซ้อน (List) -> List ไว้เบื้องหลังชื่อสั้น ลายเซ็นเชอร์ของ findUsers กลายเป็นที่อ่านได้: “รับ UserFilter, คืน List” typealias OnClickListener ทำให้โค้ดดูเหมือนการประกาศอินเทอร์เฟสแต่ไม่มีโอเวอร์เฮ็ดของการสร้างอินเทอร์เฟสหรือคลาสนามธรรมแยกต่างหากกัน ในขณะดียวกัน lambda และฟังก์ชันนิรนามยังคงทำงานได้ตามปกติ — typealias ไม่ต้องการเปลี่ยนแปลงในโค้ดที่เรียกใช้

Typealias กับ Generics

Typealias รองรับพารามิเตอร์ทั่วไป ทำให้มันมีความยืดหยุ่นยิ่งขึ้น คุณสามารถกำหนด typealias Mapper = (T) -> R และใช้กับชนิดใดก็ได้ คอมไพเลอร์แทนที่ชนิดเฉพาะสำหรับพารามิเตอร์ในการใช้นามแฝงแต่ละครั้ง โดยรักษาความปลอดภัยของชนิดอย่างสมบูรณ์

kotlin
// Generic typealias
typealias Mapper<T, R> = (T) -> R
typealias Provider<T> = () -> T
typealias ListTransformer<T> = (List<T>) -> List<T>

fun processNumbers(mapper: Mapper<Int, String>) {
    // mapper type is (Int) -> String
}

fun main() {
    val config: Provider<String> = { "default config" }
    val reverse: ListTransformer<Int> = { it.reversed() }
}

ในรายการ Mapper เป็นนามแฝงทั่วไปสำหรับการแปลงใดๆ จาก T ไปยัง R Provider คือตัวให้ค่า (โรงงานที่ไม่มีอาร์กิวเมนต์) ListTransformer คือฟังก์ชันแปลงรายการ เมื่อเรียก processNumbers(mapper: Mapper) คอมไพเลอร์จะขยายนามแฝงเป็น (Int) -> String Generics ทำให้ typealias กลายเป็นเครื่องมือสากลที่เหมาะกับทุกบริบทโดยไม่ต้องทำซ้ำการประกาศ

Typealias สำหรับชื่อที่ซ้อนกันและยาว

คลาสที่ซ้อนกันและชนิดที่มีพารามิเตอร์ยาวเป็นอีกพื้นที่ที่ typealias ทำให้โค้ดง่ายขึ้นอย่างมาก หากคลาสอยู่ลึกในลำดับชั้นสมเทษ (Outer.Inner.Nested) การอ้างถึงชื่อเต็มจะทำให้โค้ดรกร้าย Typealias ย่อการเข้าถึงดังกล่าวและทำให้อ่านง่ายขึ้น โดยเฉพาะอย่างยิ่งสำหรับคลาสจากไลบรารีของบุคคลที่สามที่มีชื่อยาว

kotlin
// Alias for nested class
class NetworkResponse {
    class Error(val code: Int, val message: String)
}
typealias NetworkError = NetworkResponse.Error

// Alias for long library type
typealias UserId = Long
typealias JsonMap = Map<String, Any?>

fun process(error: NetworkError) {
    println("${error.code}: ${error.message}")
}

fun parseJson(data: JsonMap): UserId {
    return data["id"] as? Long ?: 0L
}

ในตัวอย่าง NetworkError เป็นนามแฝงสำหรับคลาสซ้อนกัน NetworkResponse.Error โดยการนำเข้า typealias คุณสามารถใช้ NetworkError เป็นชนิดปกติโดยไม่ต้องเปิดเผยลำดับชั้นสมเทษ JsonMap บันทึกว่าแผนที่แสดงถึงวัตถุ JSON UserId ชี้แจงวัตถุประสงค์ของ Long ในบริบทเฉพาะ — ผู้อ่านเข้าใจทันทีว่านี้คือตัวระบุผู้ใช้ ไม่ใช่ตัวเลขที่เรียกได้ตามอำเภอ อย่างไรก็ตาม typealias ไม่ป้องกันการส่ง Long ทั่วไปไปยังที่ที่คาดหวัง UserId — สำหรับเรื่องนั้นต้องใช้ value class

Typealias vs Inline Class: ความแตกต่าง

Typealias และ inline class (value class) แก้ปัญหาที่แตกต่างกัน แม้ว่าทั้งสองจะแนะนำชื่อใหม่สำหรับชนิดก็ตาม Typealias เป็นเพียงคำพ้อง: ตัวแปรชนิด UserId = Long รับ Long ใดๆ โดยไม่มีการตรวจสอบ Inline class ห่อค่าในชนิดใหม่ที่ถูกตรวจสอบในขณะแปลง: ไม่สามารถส่ง Long ทั่วไปไปยังที่ที่คาดหวัง inline class UserId โดยไม่มีการแปลงอย่างชัดเจน

ลักษณะTypealiasInline class
ชนิดใหม่ไม่ — คำพ้องของต้นฉบับใช่ — ชนิดใหม่พร้อมการตรวจสอบ
ประสิทธิภาพศูนย์ — ถูกลบอย่างสมบูรณ์ศูนย์ — ตัวห่อถูกลบออกในไบต์โค้ด
การสืบทอดไม่ไม่ (คลาสจบ)
เมธอดของตัวเองไม่ใช่ — สามารถประกาศฟังก์ชันได้
ความปลอดภัยของชนิดไม่ — แลกเปลี่ยนกับต้นฉบับได้ใช่ — คอมไพเลอร์แยกแยะชนิด

ตารางแสดงความแตกต่างระหว่างกลไกทั้งสอง Typealias เหมาะสำหรับชื่อที่กระชับและการบันทึกโค้ดเมื่อไม่ต้องการการพิมพ์ที่เคร่งครัด Inline class ผ่านคำสำคัญ value class (เดิมคือ inline class) จำเป็นเมื่อจำเป็นต้องแยกแยะค่าที่แตกต่างกันทางความหมายของชนิดเดิมเดียวกัน ตัวอย่างเช่น UserId และ OrderId ล้วนเป็น Long แต่การส่งตัวหนึ่งไปยังที่ที่คาดหวังอีกตัวเป็นข้อผิดพลาดทางตรรกะที่ value class ป้องกันได้ในขณะแปลง

คำถามที่พบบ่อย

Typealias แตกต่างจาก import alias อย่างไร?

Import alias (import com.example.LongName as Short) ทำงานในระดับการนำเข้า — จะย่อชื่อเฉพาะในไฟล์ปัจจุบัน Typealias ประกาศนามแฝงทั่วโลกที่สามารถใช้ได้ทั่งโปรเจคหลังจากการนำเข้า

สามารถใช้ typealias สร้างชนิดแบบเรียกซ้ำได้หรือไม่?

ได้ typealias รองรับนิยามแบบเรียกซ้ำสำหรับชนิดฟังก์ชัน แต่ต้องระมัดระวัง: typealias Rec = (T) -> Rec ทำงานได้ แต่การอ้างถึงแบบเรียกซ้ำไปยัง object ไม่ได้ คอมไพเลอร์จะตรวจสอบวงจรและสร้างข้อผิดพลาดสำหรับนิยามที่ไม่มีที่สิ้นสุด

Typealias มีผลต่อประสิทธิภาพหรือไม่?

ไม่ typealias ถูกลบอย่างสมบูรณ์ในขณะแปลง ชนิดต้นฉบับจะถูกใช้ในระดับไบต์โค้ดและรันไทมโดยไม่มีตัวห่อ ประสิทธิภาพเหมือนกับการใช้ชนิดต้นฉบับโดยตรง

ระดับการซ้อนกันสูงสุดสำหรับ typealias คือเท่าไร?

Typealias สามารถอ้างถึง typealias อื่นได้ — เรียกว่าสายโส้ของนามแฝง ความลึกของสายโส้ไม่มีข้อจำกัดอย่างเป็นทางการ แต่เพื่อความสามารถอ่านได้ ไม่ควรเกิน 2–3 ระดับ คอมไพเลอร์จะแก้ไขสายโส้อย่างสมบูรณ์ในขั้นตอนการวิเคราะห์

สามารถประกาศ typealias ภายในฟังก์ชันได้หรือไม่?

ไม่ typealias เป็นการประกาศระดับบนสุดหรือสมาชิกของคลาส/วัตถุ ไม่สามารถประกาศ typealias ภายในฟังก์ชัน สำหรับการย่อชนิดในท้องถิ่น ใช้ import alias ภายในไฟล์หรือวาง typealias ไว้ในระดับโมดูล

สรุป

  • Typealias — คำพ้องสำหรับชนิดที่มีอยู่แล้ว ไม่สร้างชนิดใหม่และถูกลบในขณะแปลง
  • ชนิดฟังก์ชัน — กรณีใช้งานหลัก: typealias แทนที่ (T) -> R ด้วยชื่อที่อ่านง่ายเช่น Callback
  • Generics ใน typealias ช่วยให้สร้างนามแฝงทั่วไป Mapper สำหรับชนิดใดก็ได้
  • คลาสซ้อนกัน — typealias ย่อการเข้าถึงชนิดที่ซ้อนกันลึกและชื่อยาวจากไลบรารี
  • ความปลอดภัยของชนิด ไม่มี: typealias สามารถแลกเปลี่ยนกับชนิดต้นฉบับได้อย่างสมบูรณ์
  • Value class — ทางเลือกแทน typealias เมื่อต้องการตรวจสอบชนิดอย่างเข้มงวนโดยไม่มีค่าใช้จ่ายในขณะรันไทม์
  • การอ่านได้ — ข้อดีหลัก: ชื่อชนิดที่มีความหมายทำให้โค้ดอธิบายตัวเองได้โดยไม่มีโอเวอร์เฮ็ด

เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร

IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม