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
// 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 делает код похожим на декларацию интерфейса, но без накладных расходов на создание отдельного интерфейса или абстрактного класса. При этом лямбды и анонимные функции продолжают работать как обычно — typealias не требует изменений в вызывающем коде.

Typealias с дженериками

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. Дженерики делают 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
Новый типНет — синоним оригиналаДа — новый тип с проверками
ПроизводительностьНулевая — стирается в нольНулевая — обёртка удаляется в байткоде
НаследованиеНетНет (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 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

Читайте также