Running Codegen

Codegen runs as part of every Android build, but you can run just that step to see what it produces before you write any Kotlin:

Generating the Turbo Native Module's codeShell
cd android
./gradlew :app:generateCodegenArtifactsFromSchema --no-daemon --max-workers=2
cd app/build/generated/source/codegen && find . -name "NativeBookShareSpec*"
Output
BUILD SUCCESSFUL in 1m 47s
30 actionable tasks: 2 executed, 28 up-to-date
./java/com/anonymous/booknest/share/NativeBookShareSpec.java
./jni/react/renderer/components/NativeBookShareSpec
./jni/react/renderer/components/NativeBookShareSpec/NativeBookShareSpecJSI.h
./jni/NativeBookShareSpec-generated.cpp
./jni/NativeBookShareSpec.h

The Java file is the class your Kotlin extends, an abstract NativeBookShareSpec that extends ReactContextBaseJavaModule and implements TurboModule. Read it before implementing, because it is the real contract:

NativeBookShareSpec.java, generated by Codegen (excerpt)JSX
  @ReactMethod
  @DoNotStrip
  public abstract void shareBook(String title, String url, Promise promise);
  @ReactMethod(isBlockingSynchronousMethod = true)
  @DoNotStrip
  public abstract double getShareCount();

Two details surprise people. The Promise<boolean> return became a trailing Promise parameter that you settle yourself. And although the spec says CodegenTypes.Int32, React Native 0.86.3 36,878 's Codegen declared the synchronous result as a double; the C++ side, NativeBookShareSpec-generated.cpp, calls it through JNI with the signature "()D". A first Kotlin draft that returned Int would not have compiled. Never edit or commit the regenerated files under build/.