Typealias là một cơ chế Kotlin để tạo tên thay thế cho một kiểu hiện có. Từ khóa typealias cho phép bạn thay thế một khai báo kiểu phức tạp bằng một bí danh ngắn và rõ ràng mà không tạo ra kiểu mới. Theo tài liệu Kotlin (2026), typealias cải thiện khả năng đọc mã, đặc biệt trong chữ ký hàm với các kiểu hàm. Typealias làm cho mã tự động được tài liệu hóa bằng cách thay thế các khai báo dài dòng bằng các kiểu được đặt tên rõ ràng.
Những điểm chính
Typealias (bí danh kiểu) là một khai báo giới thiệu một tên thay thế cho một kiểu hiện có. Cú pháp: typealias TênMới = KiểuHiệnTại. Sau khi khai báo, TênMới có thể được sử dụng ở bất cứ đâu mà KiểuHiệnTại được mong đợi — trình biên dịch coi chúng là cùng một kiểu. Ở cấp độ bytecode, typealias không để lại dấu vết: tất cả thông tin bí danh đều bị xóa trong quá trình biên dịch.
Mục đích chính của typealias là cải thiện khả năng đọc mã. Thay vì một chữ ký dài dòng fun process(callback: (Result) -> Unit), bạn có thể viết typealias Callback = (Result) -> Unit và sử dụng Callback làm kiểu tham số. Điều này đặc biệt hữu ích khi cùng một kiểu hàm được lặp lại ở nhiều nơi trong mã: bí danh đóng vai trò là một điểm định nghĩa duy nhất và ghi lại mục đích của kiểu.
Typealias không tạo ra kiểu mới — nó chỉ là một từ đồng nghĩa. Các biến kiểu Callback và (Result) -> Unit có thể thay thế hoàn toàn cho nhau. Trình biên dịch sẽ không báo lỗi nếu một lambda được truyền trực tiếp vào một hàm mong đợi Callback. Điều này phân biệt typealias với inline class (value class), tạo ra một kiểu bao bọc mới với kiểm tra lúc biên dịch. Typealias là đổi tên, không phải bao bọc.
Trường hợp sử dụng phổ biến nhất của typealias trong Kotlin là các kiểu hàm. Các chữ ký dài như (Int, String) -> Boolean hoặc (List
// 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 = {}
}
Trong ví dụ, typealias UserFilter ẩn kiểu hàm phức tạp (List
Typealias hỗ trợ tham số tổng quát (generic), khiến nó càng linh hoạt hơn. Bạn có thể định nghĩa typealias Mapper
// 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() }
}
Trong danh sách, Mapper
Các lớp lồng nhau và các kiểu được tham số hóa dài là một lĩnh vực khác mà typealias đơn giản hóa đáng kể mã. Nếu một lớp nằm sâu trong hệ phân cấp lồng nhau (Outer.Inner.Nested), việc tham chiếu nó bằng tên đầy đủ sẽ làm mã trở nên lộn xộn. Typealias rút ngắn truy cập đó và làm cho nó dễ đọc hơn. Điều này đặc biệt phù hợp cho các lớp từ thư viện bên thứ ba với tên dài.
// 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
}
Trong ví dụ, NetworkError là một bí danh cho lớp lồng nhau NetworkResponse.Error. Bằng cách nhập typealias, bạn có thể sử dụng NetworkError như một kiểu thông thường mà không cần tiết lộ hệ phân cấp lồng nhau. JsonMap ghi lại rằng bản đồ đại diện cho một đối tượng JSON. UserId làm rõ mục đích của Long trong một ngữ cảnh cụ thể — người đọc hiểu ngay rằng đây là một định danh người dùng, không phải một số tùy ý. Tuy nhiên, typealias không ngăn việc truyền một Long đơn giản vào nơi UserId được mong đợi — để làm điều đó, cần có value class.
Typealias và inline class (value class) giải quyết các vấn đề khác nhau, mặc dù cả hai đều giới thiệu một tên mới cho một kiểu. Typealias chỉ là một từ đồng nghĩa: một biến kiểu UserId = Long chấp nhận bất kỳ Long nào mà không kiểm tra. Inline class bao bọc một giá trị trong một kiểu mới được kiểm tra lúc biên dịch: không thể truyền một Long đơn giản vào nơi mà một inline class UserId được mong đợi nếu không có chuyển đổi tường minh.
| Đặc điểm | Typealias | Inline class |
|---|---|---|
| Kiểu mới | Không — từ đồng nghĩa của bản gốc | Có — kiểu mới với kiểm tra |
| Hiệu suất | Không — bị xóa hoàn toàn | Không — bao bọc được loại bỏ trong bytecode |
| Kế thừa | Không | Không (lớp cuối cùng) |
| Phương thức riêng | Không | Có — có thể khai báo hàm |
| An toàn kiểu | Không — có thể thay thế cho bản gốc | Có — trình biên dịch phân biệt kiểu |
Bảng thể hiện sự khác biệt giữa hai cơ chế. Typealias phù hợp cho các tên ngắn gọn và tài liệu mã khi không cần kiểu chặt chẽ. Inline class thông qua từ khóa value class (trước đây là inline class) cần thiết khi cần phân biệt các giá trị khác nhau về mặt ngữ nghĩa của cùng một kiểu nguyên thủy. Ví dụ, UserId và OrderId đều là Long, nhưng truyền cái này vào nơi mong đợi cái kia là một lỗi logic mà value class ngăn chặn ngay từ lúc biên dịch.
Các câu hỏi thường gặp
Import alias (import com.example.LongName as Short) hoạt động ở cấp độ nhập khẩu — nó rút ngắn tên chỉ trong tệp hiện tại. Typealias khai báo một bí danh toàn cục có sẵn trong toàn bộ dự án sau khi nhập.
Có, typealias hỗ trợ định nghĩa đệ quy cho các kiểu hàm, nhưng cẩn thận: typealias Rec
Không, typealias bị xóa hoàn toàn trong quá trình biên dịch. Kiểu gốc được sử dụng ở cấp bytecode và runtime mà không có bao bọc nào. Hiệu suất giống hệt như sử dụng trực tiếp kiểu gốc.
Typealias có thể tham chiếu đến một typealias khác — được gọi là chuỗi bí danh. Độ sâu của chuỗi không bị giới hạn chính thức, nhưng để dễ đọc, không nên quá 2–3 cấp. Trình biên dịch giải quyết hoàn toàn chuỗi trong giai đoạn phân tích.
Không, typealias là khai báo ở cấp cao nhất hoặc thành viên của một lớp/đối tượng. Typealias không thể được khai báo trong các hàm. Để rút ngắn kiểu cục bộ, hãy sử dụng import alias trong tệp hoặc đặt typealias ở cấp mô-đun.
Tổng kết
Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay
IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.
Đọc thêm