Typealias to mechanizm Kotlin do tworzenia alternatywnej nazwy istniejącego typu. Słowo kluczowe typealias pozwala zastąpić złożoną deklarację typu krótkim i zrozumiałym aliasem, nie tworząc nowego typu. Według dokumentacji Kotlin (2026), typealias zwiększa czytelność kodu, szczególnie w sygnaturach funkcji z typami funkcyjnymi. Typealias sprawia, że kod staje się samodokumentujący, zastępując wielosłowne deklaracje zrozumiałymi nazwanymi typami.
Najważniejsze
Typealias (alias typu) — to deklaracja wprowadzająca alternatywną nazwę dla istniejącego typu. Składnia: typealias NowaNazwa = IstniejącyTyp. Po deklaracji NowaNazwa może być używana wszędzie tam, gdzie oczekiwany jest IstniejącyTyp — kompilator traktuje je jako jeden i ten sam typ. Na poziomie kodu bajtowego typealias nie pozostawia śladów: wszystkie informacje o aliasie są usuwane na etapie kompilacji.
Głównym celem typealias jest poprawa czytelności kodu. Zamiast wielosłownej sygnatury fun process(callback: (Result) -> Unit) można napisać typealias Callback = (Result) -> Unit i używać Callback jako typu parametru. Jest to szczególnie przydatne, gdy ten sam typ funkcyjny powtarza się w wielu miejscach kodu: alias służy jako pojedynczy punkt definicji i dokumentuje przeznaczenie typu.
Typealias nie tworzy nowego typu — to tylko synonim. Zmienne typu Callback i (Result) -> Unit są w pełni wymienne. Kompilator nie zgłosi błędu, jeśli do funkcji oczekującej Callback zostanie przekazana lambda bezpośrednio. To odróżnia typealias od inline class (value class), która tworzy nowy typ-opakowujący z kontrolą na etapie kompilacji. Typealias to zmiana nazwy, a nie opakowanie.
Najczęstszym scenariuszem użycia typealias w Kotlin są typy funkcyjne. Długie sygnatury takie jak (Int, String) -> Boolean czy (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 = {}
}
W przykładzie typealias UserFilter ukrywa złożony typ funkcyjny (List
Typealias obsługuje parametry uogólnione (generyki), co czyni go jeszcze bardziej elastycznym. Można zdefiniować 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() }
}
W listingu Mapper
Klasy zagnieżdżone i długie sparametryzowane typy — to kolejny obszar, w którym typealias znacząco upraszcza kod. Jeśli klasa znajduje się głęboko w hierarchii zagnieżdżenia (Outer.Inner.Nested), odwołanie do niej przez pełną nazwę zaśmieca kod. Typealias skraca taki dostęp i czyni go bardziej czytelnym. Jest to szczególnie istotne w przypadku klas z bibliotek zewnętrznych o długich nazwach.
// 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
}
W przykładzie NetworkError — to alias dla zagnieżdżonej klasy NetworkResponse.Error. Przy imporcie typealias można używać NetworkError jako zwykłego typu, nie ujawniając hierarchii zagnieżdżenia. JsonMap dokumentuje, że mapa reprezentuje obiekt JSON. UserId wyjaśnia przeznaczenie Long w konkretnym kontekście — czytelnik od razu rozumie, że to identyfikator użytkownika, a nie dowolna liczba. Typealias nie chroni jednak przed przekazaniem zwykłego Long tam, gdzie oczekiwane jest UserId — do tego potrzebny jest value class.
Typealias i inline class (value class) rozwiązują różne zadania, choć oba wprowadzają nową nazwę dla typu. Typealias to tylko synonim: zmienna typu UserId = Long przyjmuje dowolny Long bez kontroli. Inline class opakowuje wartość w nowy typ, który jest sprawdzany na etapie kompilacji: przekazanie zwykłego Long tam, gdzie oczekiwany jest inline class UserId, jest niemożliwe bez jawnej konwersji.
| Cecha | Typealias | Inline class |
|---|---|---|
| Nowy typ | Nie — synonim oryginału | Tak — nowy typ z kontrolą |
| Wydajność | Zerowa — usuwany całkowicie | Zerowa — opakowanie usuwane w kodzie bajtowym |
| Dziedziczenie | Nie | Nie (final class) |
| Własne metody | Nie | Tak — można deklarować funkcje |
| Bezpieczeństwo typów | Nie — wymienny z oryginałem | Tak — kompilator rozróżnia typy |
Tabela pokazuje różnicę między tymi dwoma mechanizmami. Typealias nadaje się do krótkich nazw i dokumentacji kodu, gdy nie jest wymagana ścisła typizacja. Inline class przez słowo kluczowe value class (wcześniej inline class) jest potrzebny, gdy ważne jest rozróżnianie semantycznie różnych wartości tego samego typu prymitywnego. Na przykład UserId i OrderId oba są Long, ale przekazanie jednego tam, gdzie oczekiwany jest drugi, to błąd logiczny, który value class zapobiega na etapie kompilacji.
Często zadawane pytania
Import alias (import com.example.LongName as Short) działa na poziomie importu — skraca nazwę tylko w bieżącym pliku. Typealias deklaruje globalny alias dostępny w całym projekcie po imporcie.
Tak, typealias obsługuje rekurencyjne definicje dla typów funkcyjnych, ale z ostrożnością: typealias Rec
Nie, typealias jest całkowicie usuwany na etapie kompilacji. W kodzie bajtowym i w runtime używany jest oryginalny typ bez żadnego opakowania. Wydajność jest identyczna z bezpośrednim użyciem oryginalnego typu.
Typealias może odnosić się do innego typealias — nazywa się to łańcuchem aliasów. Głębokość łańcucha formalnie nie jest ograniczona, ale dla czytelności zaleca się nie więcej niż 2–3 poziomy. Kompilator rozwija łańcuch całkowicie na etapie analizy.
Nie, typealias to deklaracja poziomu najwyższego lub element klasy/obiektu. Wewnątrz funkcji nie można zadeklarować typealias. Do lokalnego skracania typów używaj import alias wewnątrz pliku lub wynieś typealias na poziom modułu.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również