Day 34: Codegen & C++ Native Bindings Basics
Understand Codegen as the type-safety and boilerplate-elimination layer that turns a JS/TS spec into generated native glue code for both platforms.
Study
Concepts
One spec, generated bindings for both platforms
Codegen reads a strictly-typed JS/TypeScript (or Flow) file describing a native module's or component's shape — method names, argument types, return types — and generates the corresponding native interface code (Objective-C++/Java/Kotlin protocol stubs, plus the C++ JSI glue) automatically at build time. Without Codegen, every new native module required hand-writing matching boilerplate on iOS and Android that could silently drift out of sync with the JS side; Codegen makes the JS spec the single source of truth and catches mismatches at build time instead of at runtime.
This is conceptually similar to how GraphQL codegen or OpenAPI codegen generate typed client code from a schema — the schema (here, the TS interface) is the contract, and the generator produces boilerplate that would otherwise be tedious and error-prone to hand-write and keep in sync across languages.
Fabric components follow the same pattern
It is not only for modules — Fabric native UI components are also defined via a typed spec (props, event types) that Codegen turns into native view manager boilerplate for iOS and Android, plus the C++ ShadowNode descriptor Fabric needs. This is why writing a New-Architecture native UI component today mostly means writing a correct TypeScript prop interface and implementing the platform-specific rendering — the cross-language wiring is generated, not hand-written.
See It
Visualizations
Visualization
From a typed JS spec to running native code
method signatures, prop types, event types
reads the spec via a Babel/Flow parser
iOS (Obj-C++/Swift) + Android (Java/Kotlin) + C++ JSI bindings
fill in the generated protocol/interface
Build It
Code Examples
A Fabric component spec — props are the contract
// RNSwitchNativeComponent.ts
import type { ViewProps } from 'react-native';
import type { BubblingEventHandler } from 'react-native/Libraries/Types/CodegenTypes';
import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
interface NativeProps extends ViewProps {
value?: boolean;
disabled?: boolean;
onValueChange?: BubblingEventHandler<{ value: boolean }>;
}
export default codegenNativeComponent<NativeProps>('RNSwitch');
// Codegen turns this into typed iOS + Android view manager boilerplate,
// so both platforms implement the SAME contract with no drift possible.Why the generated typing matters — a caught mismatch
// If native Swift code returns a String where the spec says number,
// Codegen-generated code fails to compile the native side — the bug
// is caught at BUILD time, not as a runtime crash/silent wrong value
// discovered by a user in production.
export interface Spec extends TurboModule {
getBatteryLevelSync(): number; // contract: must return a number
}
// -> generated ObjC++/JNI signatures enforce this at compile time on both platformsRemember
Key Takeaways
- Codegen turns one typed JS/TS spec into generated native glue for iOS, Android, and the C++ JSI bindings.
- The JS spec becomes the single source of truth — type mismatches are caught at build time, not discovered at runtime.
- Fabric UI components use the same pattern: a typed props/events interface generates native view manager boilerplate.
- This is conceptually the same idea as GraphQL/OpenAPI codegen — generate boilerplate from a schema instead of hand-writing it per language.
- In practice, building a New Architecture native module today means: write the spec, implement native logic, let Codegen wire the rest.
Do It
Practice
- 1Write a TurboModule spec for a "SecureStorage" module (getItem/setItem/removeItem) with fully typed signatures.
- 2Read through one real generated Codegen output file (from an actual RN project's build folder) and identify the JSI glue vs the platform-specific stub.
- 3Explain in writing why "the JS spec is the source of truth" reduces bugs compared to hand-writing matching native interfaces per platform.