Typealias — какво е, синтаксис и приложение в Kotlin

Автор: IT Sectr Публикувано: 2026-06-23 Време за четене: 7 мин

Typealias е механизъм в Kotlin за създаване на алтернативно име на съществуващ тип. Ключовата дума typealias позволява замяна на сложна декларация на тип с кратък и разбираем псевдоним, без да се създава нов тип. Според документацията на Kotlin (2026), typealias подобрява четливостта на кода, особено в сигнатурите на функции с функционални типове. Typealias прави кода самодокументиращ се, като заменя многословните декларации с разбираеми именувани типове.

Основни точки

  • Typealias — псевдоним за съществуващ тип, не създава нов тип
  • Функционални типове — typealias заменя сложни (T) -> R с четливи имена като Callback
  • Генерици — 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 са напълно взаимозаменяеми. Компилаторът няма да даде грешка, ако във функция, очакваща Callback, се подаде директно ламбда. Това отличава typealias от inline class (value class), който създава нов тип-обвивка с проверка на етапа на компилация. Typealias е преименуване, а не обвивка.

Typealias за функционални типове

Най-честият сценарий за използване на typealias в Kotlin са функционалните типове. Дълги сигнатури като (Int, String) -> Boolean или (List) -> Result правят кода труден за четене. Typealias ги превръща в кратки смислени имена, които документират предназначението на функцията: typealias Validator = (String) -> Boolean указва, че това е валидатор на низове.

kotlin
// Без 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) -> List зад кратко име. Сигнатурата findUsers става четлива: «приема UserFilter, връща List». Typealias OnClickListener прави кода подобен на декларация на интерфейс, но без допълнителната тежест от създаване на отделен интерфейс или абстрактен клас. Ламбдите и анонимните функции продължават да работят както обикновено — typealias не изисква промени в извикващия код.

Typealias с генерици

Typealias поддържа обобщени параметри (генерици), което го прави още по-гъвкав. Може да се дефинира typealias Mapper = (T) -> R и да се използва с всякакви типове. Компилаторът замества конкретни типове на мястото на параметрите при всяко използване на псевдонима, запазвайки пълна типова безопасност.

kotlin
// Обобщен 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 — обобщен псевдоним за всякакво преобразуване от T в R. Provider — доставчик на стойност (фабрика без аргументи). ListTransformer — функция за преобразуване на списък. При извикване processNumbers(mapper: Mapper) компилаторът разгъва псевдонима до (Int) -> String. Генериците правят typealias универсален инструмент, подходящ за всякакви контексти без дублиране на декларации.

Typealias за вложени класове и дълги имена

Вложените класове и дългите параметризирани типове — още една област, в която typealias значително опростява кода. Ако даден клас е дълбоко в йерархията на влагане (Outer.Inner.Nested), позоваването на него с пълно име затрупва кода. Typealias съкращава този достъп и го прави по-четлив. Това е особено важно за класове от външни библиотеки с дълги имена.

kotlin
// Псевдоним за вложен клас
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 vs inline class: разлики

Typealias и inline class (value class) решават различни задачи, въпреки че и двата въвеждат ново име за тип. Typealias е просто синоним: променлива от тип UserId = Long приема произволен Long без проверка. Inline class обвива стойността в нов тип, който се проверява на етапа на компилация: предаването на обикновен Long там, където се очаква inline class UserId, е невъзможно без изрично преобразуване.

ХарактеристикаTypealiasInline class
Нов типНе — синоним на оригиналаДа — нов тип с проверки
ПроизводителностНулева — напълно се изтриваНулева — обвивката се премахва в байткода
НаследяванеНеНе (final 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 се изтрива напълно на етапа на компилация. В байткода и runtime се използва оригиналният тип без никаква обвивка. Производителността е идентична с директното използване на оригиналния тип.

Какво е максималното ниво на влагане за typealias?

Typealias може да препраща към друг typealias — това се нарича верига от псевдоними. Дълбочината на веригата формално не е ограничена, но за четливост се препоръчва не повече от 2–3 нива. Компилаторът разгъва веригата напълно на етапа на анализ.

Може ли да се декларира typealias вътре във функция?

Не, typealias е декларация от най-високо ниво или член на клас/обект. Вътре във функции не може да се декларира typealias. За локално съкращаване на типове използвайте import alias във файла или извадете typealias на ниво модул.

Обобщение

  • Typealias — синоним за съществуващ тип, не създава нов тип и се изтрива на етапа на компилация
  • Функционални типове — основната област на приложение: typealias заменя (T) -> R с четливо име като Callback
  • Генерици в typealias позволяват създаване на обобщени псевдоними Mapper за всякакви типове
  • Вложени класове — typealias съкращава достъпа до дълбоко вложени типове и дълги имена от библиотеки
  • Типова безопасност липсва: typealias е напълно взаимозаменяем с оригиналния тип
  • Value class — алтернатива на typealias, когато е нужна строга проверка на типовете с нулева цена в runtime
  • Четливост — основното предимство: смислени имена на типове правят кода самодокументиращ се без допълнителна тежест

Ще разработим мобилно приложение под ключ

IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.

Обсъдете проекта

Прочетете също