Typealias е механизъм в Kotlin за създаване на алтернативно име на съществуващ тип. Ключовата дума typealias позволява замяна на сложна декларация на тип с кратък и разбираем псевдоним, без да се създава нов тип. Според документацията на Kotlin (2026), typealias подобрява четливостта на кода, особено в сигнатурите на функции с функционални типове. Typealias прави кода самодокументиращ се, като заменя многословните декларации с разбираеми именувани типове.
Основни точки
Typealias (псевдоним на тип) — декларация, която въвежда алтернативно име за съществуващ тип. Синтаксис: typealias НовоИме = СъществуващТип. След декларацията НовоИме може да се използва навсякъде, където се очаква СъществуващТип — компилаторът ги третира като един и същ тип. На ниво байткод typealias не оставя следи: цялата информация за псевдонима се изтрива на етапа на компилация.
Основната цел на typealias е подобряване на четливостта на кода. Вместо дълга сигнатура fun process(callback: (Result) -> Unit) може да се напише typealias Callback = (Result) -> Unit и да се използва Callback като тип на параметър. Това е особено полезно, когато един и същ функционален тип се повтаря на няколко места в кода: псевдонимът служи като единична точка на дефиниция и документира предназначението на типа.
Typealias не създава нов тип — това е просто синоним. Променливите от тип Callback и (Result) -> Unit са напълно взаимозаменяеми. Компилаторът няма да даде грешка, ако във функция, очакваща Callback, се подаде директно ламбда. Това отличава typealias от inline class (value class), който създава нов тип-обвивка с проверка на етапа на компилация. Typealias е преименуване, а не обвивка.
Най-честият сценарий за използване на typealias в Kotlin са функционалните типове. Дълги сигнатури като (Int, String) -> Boolean или (List
// Без typealias
fun findUsers(
filter: (List<User>) -> List<User>
): List<User>
// С typealias
typealias UserFilter = (List<User>) -> List<User>
fun findUsers(filter: UserFilter): List<User>
// Употреба в клас
typealias OnClickListener = (View) -> Unit
class Button {
var onClick: OnClickListener = {}
}
В примера typealias UserFilter скрива сложния функционален тип (List
Typealias поддържа обобщени параметри (генерици), което го прави още по-гъвкав. Може да се дефинира typealias Mapper
// Обобщен 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 типът е (Int) -> String
}
fun main() {
val config: Provider<String> = { "default config" }
val reverse: ListTransformer<Int> = { it.reversed() }
}
В листинга Mapper
Вложените класове и дългите параметризирани типове — още една област, в която typealias значително опростява кода. Ако даден клас е дълбоко в йерархията на влагане (Outer.Inner.Nested), позоваването на него с пълно име затрупва кода. Typealias съкращава този достъп и го прави по-четлив. Това е особено важно за класове от външни библиотеки с дълги имена.
// Псевдоним за вложен клас
class NetworkResponse {
class Error(val code: Int, val message: String)
}
typealias NetworkError = NetworkResponse.Error
// Псевдоним за дълъг библиотечен тип
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 и inline class (value class) решават различни задачи, въпреки че и двата въвеждат ново име за тип. Typealias е просто синоним: променлива от тип UserId = Long приема произволен Long без проверка. Inline class обвива стойността в нов тип, който се проверява на етапа на компилация: предаването на обикновен Long там, където се очаква inline class UserId, е невъзможно без изрично преобразуване.
| Характеристика | Typealias | Inline class |
|---|---|---|
| Нов тип | Не — синоним на оригинала | Да — нов тип с проверки |
| Производителност | Нулева — напълно се изтрива | Нулева — обвивката се премахва в байткода |
| Наследяване | Не | Не (final class) |
| Собствени методи | Не | Да — могат да се декларират функции |
| Типова безопасност | Не — взаимозаменяем с оригинала | Да — компилаторът различава типовете |
Таблицата показва разликата между двата механизма. Typealias е подходящ за кратки имена и документиране на код, когато не се изисква строга типизация. Inline class чрез ключовата дума value class (преди inline class) е необходим, когато е важно да се разграничават семантично различни стойности на един и същ примитивен тип. Например UserId и OrderId и двете са Long, но предаването на едното там, където се очаква другото, е логическа грешка, която value class предотвратява на етапа на компилация.
Често задавани въпроси
Import alias (import com.example.LongName as Short) работи на ниво импорт — съкращава името само в текущия файл. Typealias декларира глобален псевдоним, достъпен в целия проект след импортиране.
Да, typealias поддържа рекурсивни дефиниции за функционални типове, но с повишено внимание: typealias Rec
Не, typealias се изтрива напълно на етапа на компилация. В байткода и runtime се използва оригиналният тип без никаква обвивка. Производителността е идентична с директното използване на оригиналния тип.
Typealias може да препраща към друг typealias — това се нарича верига от псевдоними. Дълбочината на веригата формално не е ограничена, но за четливост се препоръчва не повече от 2–3 нива. Компилаторът разгъва веригата напълно на етапа на анализ.
Не, typealias е декларация от най-високо ниво или член на клас/обект. Вътре във функции не може да се декларира typealias. За локално съкращаване на типове използвайте import alias във файла или извадете typealias на ниво модул.
Обобщение
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също