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は名前の変更であり、ラップではありません。
Kotlinでのtypealiasの最も一般的な使用例は関数型です。(Int, String) -> Boolean や (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 = {}
}
この例では、typealias UserFilter が複雑な関数型 (List
Typealiasはジェネリックパラメータをサポートしており、さらに柔軟性が高まります。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() }
}
リストでは、Mapper
ネストされたクラスと長いパラメータ化された型は、typealiasがコードを大幅に簡素化するもう1つの領域です。クラスがネスト階層(Outer.Inner.Nested)の深いところにある場合、完全な名前で参照するとコードが乱雑になります。Typealiasはそのようなアクセスを短縮し、より読みやすくします。これは特に、長い名前を持つサードパーティライブラリのクラスに関連します。
// 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はUserIdが期待される場所にプレーンなLongを渡すことを防ぎません — そのためにはvalue classが必要です。
Typealias と inline class(value class)は、どちらも型に新しい名前を導入しますが、異なる問題を解決します。Typealiasは単なる同義語です:UserId = Long 型の変数はチェックなしで任意のLongを受け入れます。Inline classは値をコンパイル時にチェックされる新しい型にラップします。inline class UserIdが期待される場所に、明示的な変換なしでプレーンなLongを渡すことはできません。
| 特徴 | Typealias | Inline class |
|---|---|---|
| 新しい型 | いいえ — 元の型の同義語 | はい — チェック付きの新しい型 |
| パフォーマンス | ゼロ — 完全に消去される | ゼロ — バイトコードでラッパーが削除される |
| 継承 | いいえ | いいえ(最終クラス) |
| 独自のメソッド | いいえ | はい — 関数を宣言可能 |
| 型安全性 | いいえ — 元の型と交換可能 | はい — コンパイラが型を区別する |
表は2つのメカニズムの違いを示しています。Typealiasは、厳密な型付けが不要な場合の簡潔な名前とコード文書化に適しています。value classキーワード(以前はinline class)によるInline classは、同じプリミティブ型の意味的に異なる値を区別することが重要な場合に必要です。たとえば、UserIdとOrderIdはどちらもLongですが、一方が期待される場所に他方を渡すことは論理エラーであり、value classがコンパイル時に防止します。
よくある質問
Import alias(import com.example.LongName as Short)はインポートレベルで機能し、現在のファイル内でのみ名前を短縮します。Typealiasはインポート後、プロジェクト全体で利用可能なグローバルエイリアスを宣言します。
はい、typealiasは関数型の再帰的定義をサポートしていますが、注意が必要です:typealias Rec
いいえ、typealiasはコンパイル時に完全に消去されます。バイトコードとランタイムレベルでは、ラッパーなしで元の型が使用されます。パフォーマンスは元の型を直接使用するのと同じです。
Typealiasは別のtypealiasを参照できます — これはエイリアスのチェーンと呼ばれます。チェーンの深さは正式には無制限ですが、可読性のために2〜3レベル以下が推奨されます。コンパイラは分析段階でチェーンを完全に解決します。
いいえ、typealiasはトップレベル宣言またはクラス/オブジェクトのメンバーです。関数内でtypealiasを宣言することはできません。ローカルな型の短縮には、ファイル内でimport aliasを使用するか、typealiasをモジュールレベルに配置してください。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。