PATTERN Cited by 1 source
API contract first across three languages¶
Problem¶
You're designing an API that must be implemented in three languages simultaneously — TypeScript (RN), Swift (iOS), Kotlin (Android). Each language has different conventions:
- TypeScript: type unions, optional params, Promise returns.
- Swift:
@objcprotocols, completion-handler callbacks, optional closures, error types. - Kotlin: interfaces, suspend functions or coroutines, nullable types.
Starting implementation before the contract is agreed means:
- You'll discover mid-implementation that one language
can't honour a design decision made by another (e.g. a TS
type union doesn't map cleanly to an
@objcprotocol). - You'll redo work that's already landed.
- Tests can't be written to a shared contract because there isn't one.
Pattern¶
Define the contract in all three languages before implementation starts. Specifically:
- Draft the TypeScript interface — most flexible typing; good starting point.
- Translate to Swift protocol (with
@objc) — catches issues with optional types, generics, union types. - Translate to Kotlin interface — catches nullable vs non-nullable, suspending vs blocking conventions.
- Walk through each method + callback together — confirm semantics align across all three.
- Agree on error types and edge cases across languages before any implementation.
- Only now start implementing — each language's impl writers can work in parallel against a frozen contract.
Why upfront¶
Zalando makes this an explicit lesson-learned in their 2025-10 post (sources/2025-10-02-zalando-accelerating-mobile-app-development-with-rendering-engine-and-react-native):
"Especially when combining three environments into one (TypeScript, Swift and Kotlin) it's crucial to first properly define these API contracts and ensure that all involved environments are compatible with this contract as early as possible. Otherwise, you run into challenges where the API design might not be feasible on all platforms, requiring you to undo work that has already been done."
The lesson comes from doing it wrong the first time — the article frames it as "getting there was not an easy step and required a proper process." Contract-first is the process they converged on.
Related principles¶
This is a specific application of the API-first principle (design the API before the implementation) scaled up to three simultaneous languages. The multi-language aspect makes it strictly harder than API-first for a single language — contract drift compounds across language boundaries.
When to reach for this pattern¶
- Any three-language API contract (TypeScript + Swift + Kotlin, commonly at the RN-native boundary).
- Any contract where one of the languages has stricter
expressiveness constraints (
@objcprotocols, for example) — plan the subset first. - Any contract that will be implemented by multiple teams in parallel — frozen contract reduces integration pain.
When not to¶
- Single-language APIs — standard API-first discipline covers it.
- Very small contracts (one method, no callbacks) — the overhead of formal three-language review may not pay off.
Seen in¶
- sources/2025-10-02-zalando-accelerating-mobile-app-development-with-rendering-engine-and-react-native — canonical wiki first source. Zalando applies this pattern to their Turbo Module + DI contracts between RN and the legacy native app.