CONCEPT Cited by 1 source
Turbo Module + DI contract¶
Turbo Module + DI contract is a three-language API contract (TypeScript + Swift + Kotlin) used to let a React Native layer communicate with the surrounding legacy native app while preserving isolation — the bridging discipline in the React Native as a package architecture. Canonicalised by Zalando's 2025-10 post.
The shape¶
Four pieces (walk-through from the post's wishlist example):
-
TypeScript turbo-module spec — the RN-side interface.
-
Swift protocol — iOS side of the contract.
-
DI injection point — a static delegate slot the legacy app registers its implementation into.
-
Kotlin equivalent — same contract mirror for Android.
-
Legacy app implements and injects. At startup, the legacy app sets
WishlistConfig.delegate = MyWishlistImpl(). RN code calls the TypeScript Spec; the RN runtime routes to the Swift/Kotlin protocol; the protocol dispatches to the injected delegate.
The standalone Developer App provides a mocked delegate — so wishlist features can be developed and tested in the Developer App without the legacy app.
Why it's "three-language"¶
The contract has to exist in TypeScript, Swift, and Kotlin simultaneously, with each declaration honouring the others. This is stricter than a two-language contract (typical RN turbo module) because:
- TS types must match Swift protocol signatures (including callback shapes, optional parameters).
- TS types must match Kotlin interface signatures.
- Swift and Kotlin must converge on the same semantic
contract even though they use different dispatch
conventions (Swift protocols with
@objc, Kotlin interfaces).
Zalando explicitly calls out the process consequence: the API contract must be defined and agreed upon before implementation starts (see patterns/api-contract-first-across-three-languages):
"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."
Why DI vs direct coupling¶
The DI slot (WishlistConfig.delegate: WishlistProtocol?)
decouples the Framework SDK from the legacy app:
- Framework SDK doesn't know which implementation is registered — it just calls through the protocol.
- Legacy app injects its implementation at startup.
- Developer App injects a mock implementation.
This is what makes the Developer App viable — without the DI slot, the SDK would hard-depend on the legacy app's wishlist implementation, and the Developer App couldn't link.
Seen in¶
- sources/2025-10-02-zalando-accelerating-mobile-app-development-with-rendering-engine-and-react-native — canonical wiki first source. Wishlist-badge increment is the worked example; pattern is presented as the standard way Zalando handles RN↔native interop.