skip to content

What visibility and scoping rules apply to a top-level `typealias` declaration, and how does a `private typealias` differ from a `public` one when used across files in the same module?

level: seniorimportance: should knowfreq 22%

answer

  1. public/internal/private (protected only for members)
  2. private = file-scoped name
  3. internal = module-scoped name
  4. Visibility hides the NAME, not the type
  5. No local (in-function) typealias

basics

~20 s

A typealias lives at file or member level and can be public, internal, or private. A private one is visible only in its own file; a public one can be used anywhere it is imported. It is still just a synonym in all cases.

solid answer

~50 s

A top-level `typealias` is a **declaration** with normal Kotlin visibility modifiers: `public` (default), `internal`, and `private`. `private` scopes the alias to **its own file**; `internal` to the **module**; `public` makes it visible to any consumer that imports it. Crucially, **visibility only governs where the *name* can be referenced** — it never changes the typing rules, because the alias is still a compile-time synonym for the underlying type. A value flowing through a `private typealias` is the *same* underlying type as one written with the full type elsewhere, so callers who can't see the alias can still pass the equivalent expanded type. Aliases obey package/import rules like other top-level declarations: you `import pkg.MyAlias` to use it in another file. They can be declared at top level or as members (where member visibility and the enclosing scope apply). They cannot be local (inside a function body).

go deeper

for a junior

Knows aliases can be public/private and live at file scope.

for a middle

Maps modifiers to scope (file/module) and knows no local aliases exist.

for a senior

Explains that visibility hides the name only, and that returning a private alias still exposes the underlying type publicly.

for a principal

Advises on API surface design — keeping alias vocabulary internal so it doesn't become an unstable part of the public contract.

## Where a typealias can live - **Top level** of a file (most common). - **Member** position (inside a class/object/interface body) — subject to the enclosing scope and member visibility. - **Not** inside a function body — local typealiases are not allowed. ## Visibility modifiers A `typealias` accepts the standard modifiers: ```kotlin public typealias PublicCache = Map<String, Int> // default; visible to importers internal typealias ModuleCache = Map<String, Int> // visible within the module private typealias FileCache = Map<String, Int> // visible only in THIS file ``` - **`public`** (default): usable anywhere the file/package is imported. - **`internal`**: usable across the **same module** (Gradle/Maven module), invisible outside it. - **`private`** at top level: usable **only within the declaring file**. - **`protected`** is allowed only for *member* typealiases (not top-level), like other member declarations. ## Crucial point: visibility names, not types Visibility controls **who can write the alias name** — it does **not** create a hidden or distinct type. Since the alias is a synonym, code that can't see `FileCache` can still produce/consume the *underlying* `Map<String, Int>`: ```kotlin // File A private typealias FileCache = Map<String, Int> fun make(): FileCache = mapOf("a" to 1) // exposes Map<String,Int> in its public signature // File B (cannot name FileCache) val c: Map<String, Int> = make() // fine: same underlying type ``` So a `private typealias` does **not** hide the type from other files; it only prevents them from using the **short name**. Public API signatures expand the alias to its underlying type in the compiled/exposed form. ## Import & package rules A top-level `typealias` is referenced across files via import, like any top-level symbol: ```kotlin import com.acme.PublicCache ``` ## Practical guidance - Use `private`/`internal` for aliases that are **implementation-local readability helpers** so they don't leak as part of your stable public vocabulary. - Remember exposing a function that *returns* a private alias still exposes the **underlying** type publicly — the alias name just won't appear to outside callers. ## Summary Visibility on a typealias is ordinary Kotlin visibility applied to a **name**; the aliased type and its assignability are unaffected.

  • If a public function returns a `private typealias`, can outside callers still use the result?
    Yes. They just can't name the alias; the signature exposes the underlying type, which they can use directly.
  • Can a typealias be `protected`?
    Only as a member typealias inside a class hierarchy; top-level typealiases can't be protected.

saying these in an interview costs you the question

  • Thinking private typealias hides the underlying type from other files
  • Believing visibility changes assignability/type identity
  • Saying typealias can be declared inside a function
  • Claiming internal means file-scoped (it is module-scoped)
  • Assuming an alias must be imported to use its underlying type

context