@ttsc/metro
v0.18.0
Published
Metro (React Native / Expo) adapter for ttsc plugins.
Maintainers
Readme
@ttsc/metro

Metro (React Native / Expo) adapter for ttsc plugins.
React Native and Expo bundle with Metro, which transpiles each file with Babel (babel-preset-expo / @react-native/metro-babel-transformer). Babel strips TypeScript types and never runs TypeScript transformers, so neither the ttsc CLI nor @ttsc/unplugin can reach an RN/Expo build. @ttsc/metro wires a Metro custom transformer that runs the ttsc plugin pass (typia, nestia, …) on each TypeScript file, then hands the result to your existing Expo/React-Native Babel transformer.
Setup
Install ttsc and TypeScript-Go first. Then install the Metro adapter:
npm install -D ttsc typescript
npm install -D @ttsc/metroWrap your Metro config with withTtsc.
Expo
// metro.config.js
const { getDefaultConfig } = require("expo/metro-config");
const { withTtsc } = require("@ttsc/metro");
module.exports = withTtsc(getDefaultConfig(__dirname));Bare React Native
// metro.config.js
const { getDefaultConfig } = require("@react-native/metro-config");
const { withTtsc } = require("@ttsc/metro");
module.exports = withTtsc(getDefaultConfig(__dirname));withTtsc sets transformer.babelTransformerPath and leaves the rest of your config untouched. It auto-detects the upstream transformer to delegate to (@expo/metro-config/babel-transformer for Expo, then @react-native/metro-babel-transformer, then the legacy metro-react-native-babel-transformer).
Configuration
By default @ttsc/metro finds the nearest tsconfig.json from the file being transformed and runs the plugins configured there: the standard ttsc model. If that is the config you want, withTtsc(getDefaultConfig(__dirname)) is enough.
Options are the second argument and mirror @ttsc/unplugin, plus a few Metro-specific knobs:
module.exports = withTtsc(getDefaultConfig(__dirname), {
project: "tsconfig.build.json",
plugins: [{ transform: "typia/lib/transform" }],
exclude: ["__tests__"],
});project: path to thetsconfig.jsonthe transformer should read (resolved fromprocess.cwd()).compilerOptions: a temporary overlay layered on the selected project config.plugins: an explicitttscplugin list override, orfalseto disable project plugins.upstreamTransformer: an explicit module path for the Babel transformer to delegate to, when auto-detection is not what you want.include/exclude: substring patterns matched against the project-relative file path, selecting which files run through thettscpass (.ts/.tsx/.cts/.mtsonly; declaration and JavaScript files always pass straight through).
Options are forwarded from the Metro config process to Metro's worker processes through the TTSC_METRO_OPTIONS environment variable, so they must stay JSON-serialisable (hence substring patterns rather than RegExp).
How it works
For each TypeScript file Metro asks to transform:
@ttsc/metroruns thettscplugin pass (reusing@ttsc/unplugin's transform core) → transformed TypeScript source.- The transformed source is handed to the upstream Expo/React-Native Babel transformer, which strips types, applies the RN transforms, and returns the Babel AST Metro consumes.
The plugin contract, tsconfig discovery, and per-build cache are identical to every other ttsc bundler integration.
Caveats (v1)
- Cost model. This release reuses
@ttsc/unplugin's transform core, which type-checks the wholetsconfigproject and caches the result per process. Metro runs transforms in a multi-process worker pool, so the project is compiled once per worker (on that worker's first file). A resident, incremental, per-file compiler shared across workers is the planned optimization, tracked in samchon/ttsc#255. - Cache invalidation. Metro keys its transform cache on per-file content plus a static transformer key. A
ttsctransform can depend on a type in another file; editing that type does not change the dependent file's content, so Metro may serve a stale transform. After changingtsconfig/plugin configuration or a depended-upon type, restart Metro with--reset-cache. - Type errors fail the build. The
ttscpass type-checks; a project type error surfaces as a Metro build error, matching the otherttscbundler integrations.
Sponsors
Thanks for your support.
Your donation encourages ttsc development.
References
Inspired by @elliots/metro-transformer-typical.
