Swift has a few lesser-known features that are genuinely useful in large codebases. One of them is @_exported, which lets a module re-export another module’s public API.
The usual import flow
In normal Swift code, each source file imports what it needs:
import Foundation
That is fine for small codebases, but in larger projects you often repeat the same imports across many files and targets.
What @_exported does
With @_exported, a module can expose another module transitively:
@_exported import Foundation
If another module imports yours, it can access Foundation symbols without importing Foundation directly.
Common multi-module use case
Imagine this setup:
// ModuleB.swift
@_exported import ModuleC
// ModuleA.swift
import ModuleB
ModuleA can now use public declarations from ModuleC through ModuleB.
When this helps
- Shared internal platform modules
- Wrapper modules that intentionally expose a curated API
- Reducing repetitive imports in deeply modular projects
What to avoid
- Do not use
@_exportedas a default in public SDKs where long-term API stability matters. - Do not use it to hide unclear architecture; if module boundaries are fuzzy, re-exporting can make dependencies harder to reason about.
- Do not assume it removes normal imports inside your own module’s source files; imports are still file-scoped.
Caveat: underscored attribute
@_exported is not part of Swift’s stable public language surface. It appears in Swift’s Underscored Attributes and is marked as strongly discouraged outside the standard library.
That means:
- behavior can change in future Swift versions
- tooling support is less predictable
- you should treat it as a pragmatic shortcut, not a long-term contract
- for standard import visibility control, prefer official access-level imports (
public import,internal import, etc.) described in SE-0409
Practical rule of thumb
Use @_exported only in modules that are intentionally acting as a dependency facade, and document that decision in the module README so consumers know the behavior is deliberate.
Final thought
@_exported can simplify dependency surfaces in modular Swift projects, but use it with intent and document why you chose it.