Type-Safe Assets for React Native
Eliminate string-based asset references forever. Generate typed TypeScript registries for images, SVGs, and Lottie animations with compile-time safety.
Without rn-typed-assets
// Before: Brittle string-based paths
<Image source={require('../../../assets/toast/info.png')} />
<LottieView source={require('../../utils/loading.json')} />With rn-typed-assets
// After: Type-safe named constants
import { Assets, Lotties } from './generated/assets.gen';
<Image source={Assets.toast.info} />
<LottieView source={Lotties.loading} />Powerful Features
Everything you need to manage React Native assets with confidence and type safety.
Zero-Config Setup
Works out of the box with the default src/assets layout. No configuration required for standard React Native projects.
Three Built-in Asset Types
Native support for images (PNG/JPG/WebP), SVGs, and Lottie animations (JSON). Each type gets its own typed export.
Deterministic Output
Generated files are stable across runs and friendly to code review. Keys are sorted alphabetically for consistent diffs.
Collision Detection
Files that normalize to the same key (e.g., harini-cry.png and harini_cry.png) are caught at generation time with clear errors.
Manifest-Backed Audit
Find and optionally delete unused assets that are no longer referenced anywhere in your source code.
Automatic Source Rewriting
The generate --inplace command rewrites every require() call and stale dotted reference in your source files automatically.
Content-Hash Diffing
Each manifest entry carries a SHA-1 hash, enabling the codemod to track files that move or are renamed without content changes.
Asset Organization
The organize command migrates flat or legacy asset directories into canonical subdirectories (images/, svgs/, lotties/).
Fully Configurable
Override paths, export names, TypeScript type imports, or add entirely new asset types via rn-typed-assets.config.js.
Programmatic API
Every function is exported for integration into your own scripts or build tools. Full control over the generation pipeline.
How It Works
A deterministic pipeline that transforms your asset directory into type-safe TypeScript.
Generation Pipeline
Scan
For each enabled asset type, recursively list files under the configured rootDir.
Normalize
Convert each filename to a stable camelCase key. Handle edge cases like numeric prefixes and collisions.
Build Registry Tree
Assemble a nested object tree from path segments. Detect and resolve branch/leaf collisions automatically.
Emit
Write assets.gen.ts (typed as const object) and assets.manifest.json (stable index of every key ↔ file mapping).
Example Asset Tree
src/assets/
toast/
info.png
warning.png
coupang/
harini-cry.png
lottie/
loading.json
svg/
logo.svgKey Normalization Rules
| Filename | Generated Key |
|---|---|
| harini-cry.png | hariniCry |
| camera_guide.png | cameraGuide |
| Info-Filled.png | infoFilled |
| 1.png | n1 (numeric prefix → n) |
| point.png alongside point/ dir | pointAsset (collision) |
Generated Output
1// src/generated/assets.gen.ts2import type { ImageRequireSource } from 'react-native';3import type { AnimationObject } from 'lottie-react-native';4export type SvgsAssetSource = unknown;5 6export const Assets = {7 coupang: {8 hariniCry: require('../assets/coupang/harini-cry.png') as ImageRequireSource,9 },10 toast: {11 info: require('../assets/toast/info.png') as ImageRequireSource,12 warning: require('../assets/toast/warning.png') as ImageRequireSource,13 },14} as const;15 16export const Lotties = {17 loading: require('../assets/lottie/loading.json') as AnimationObject,18} as const;19 20export const Svgs = {21 logo: require('../assets/svg/logo.svg') as SvgsAssetSource,22} as const;Quick Start
Get up and running in minutes. Works with your existing React Native project structure.
Why use typed assets?
Install the package
Add rn-typed-assets as a dev dependency. TypeScript must be available in your project (most RN projects already have it).
npm install --save-dev rn-typed-assetsAdd scripts to package.json
Configure convenient npm scripts for generation, organization, and auditing.
{
"scripts": {
"assets:generate": "rn-typed-assets generate",
"assets:generate:inplace": "rn-typed-assets generate --inplace",
"assets:organize": "rn-typed-assets organize src/assets",
"assets:audit": "rn-typed-assets audit",
"assets:audit:fix": "rn-typed-assets audit --fix"
}
}Run the generator
Execute the generate command to create assets.gen.ts and assets.manifest.json in src/generated/.
npm run assets:generateImport and use
Import the typed registry and use named constants instead of require() paths.
import { Assets, Lotties, Svgs } from './generated/assets.gen';
// Images
<Image source={Assets.toast.info} />
<Image source={Assets.coupang.hariniCry} />
// Lottie animations
<LottieView source={Lotties.loading} autoPlay loop />
// SVGs (with react-native-svg)
<SvgUri source={Svgs.logo} />Audit for unused assets
Run the audit command to find and optionally remove unused assets from your codebase.
npm run assets:audit # report unused entries
npm run assets:audit -- --fix # delete unused files and regenerateCLI Reference
Three commands to generate, organize, and audit your assets.
generate
Scan asset directories and emit assets.gen.ts + assets.manifest.json.
Options
| Flag | Description | Default |
|---|---|---|
| --types <types> | Comma-separated asset types | image,svg,lottie |
| --inplace | Rewrite source files after regen | false |
| --root <path> | Project root directory | cwd |
| --config <path> | Path to config file | ./rn-typed-assets.config.js |
Examples
rn-typed-assets generate
rn-typed-assets generate --inplace
rn-typed-assets generate --types=image,lottieorganize
Move asset files into canonical subdirectories, then regenerate and rewrite sources.
Creates: images/, svgs/, lotties/ subdirectories
Options
| Flag | Description | Default |
|---|---|---|
| <assetsDir> | Path to the asset root to organize | (required) |
| --types <types> | Asset types to move | image,svg,lottie |
Examples
rn-typed-assets organize src/assetsaudit
Compare manifest against actual source-file usages.
Options
| Flag | Description | Default |
|---|---|---|
| --types <types> | Asset types to audit | image,svg,lottie |
| --fix | Delete unused files and regenerate | false |
Examples
rn-typed-assets audit
rn-typed-assets audit --fix
rn-typed-assets audit --types=imageConfiguration
Zero config by default, fully customizable when you need it.
Full Configuration
Create rn-typed-assets.config.js in your project root to override defaults. The file is optional — omitting it accepts all defaults.
1// rn-typed-assets.config.js2module.exports = {3 // Where to write assets.gen.ts and assets.manifest.json4 // Default: 'src/generated'5 outputDir: 'src/generated',6 7 // Directories and entry files scanned by the audit command8 // Default: ['src', 'App.tsx', 'index.js']9 sourceRoots: ['src', 'App.tsx', 'index.js'],10 11 // Per-type configuration (all fields are optional overrides)12 types: {13 image: {14 rootDir: 'src/assets', // scan root15 extensions: ['.png', '.jpg', '.jpeg', '.webp'],16 exportName: 'Assets', // export const Assets = ...17 typeImport: {18 typeName: 'ImageRequireSource', // TypeScript type name19 from: 'react-native', // import source20 },21 },22 svg: {23 rootDir: 'src/assets/svg',24 extensions: ['.svg'],25 exportName: 'Svgs',26 inlineType: 'unknown', // emits: export type SvgsAssetSource = unknown27 },28 lottie: {29 rootDir: 'src/assets/lottie',30 extensions: ['.json'],31 exportName: 'Lotties',32 typeImport: {33 typeName: 'AnimationObject',34 from: 'lottie-react-native',35 },36 },37 },38};Adding Custom Types
Any type not in the defaults can be added under types. The audit command discovers it automatically via the exportName → type reverse map.
// Adding a custom font asset type
module.exports = {
types: {
font: {
rootDir: 'src/assets/fonts',
extensions: ['.ttf', '.otf'],
exportName: 'Fonts',
inlineType: 'string', // emits: export type FontsAssetSource = string
},
},
};Configuration Options
outputDirDirectory for generated files
sourceRootsFiles/dirs scanned by audit command
rootDirAsset scan root for each type
extensionsFile extensions to include
exportNameName of exported constant
typeImport / inlineTypeTypeScript type configuration
CI Integration
Integrate with your CI pipeline to catch drift between the manifest and filesystem.
GitHub Actions
Add to your CI pipeline to verify the manifest is up to date. Fails if there are uncommitted changes.
# .github/workflows/ci.yml
- name: Verify asset manifest is up to date
run: |
npm run assets:generate
git diff --exit-code src/generated/Husky Pre-commit
Automatically regenerate and stage assets before each commit using Husky git hooks.
# .husky/pre-commit
npm run assets:generate
git add src/generated/assets.gen.ts src/generated/assets.manifest.jsonBeautiful Code Highlighting for Every Language
Professional syntax highlighting powered by Shiki with support for 25+ programming languages. Optimized for readability and accessibility.
1interface User {2 id: number;3 name: string;4 email: string;5 roles: string[];6}7 8async function fetchUser(id: number): Promise<User> {9 const response = await fetch(`/api/users/${id}`);10 11 if (!response.ok) {12 throw new Error(`Failed to fetch user: ${response.status}`);13 }14 15 return response.json();16}17 18// Usage with type safety19const user = await fetchUser(123);20console.log(`Welcome, ${user.name}!`);Token Color Reference
Language keywords (const, function, if, return)
String literals and template strings
Comments and documentation
Function names and method calls
Variables and identifiers
Numeric literals
Type annotations and interfaces
Operators (+, -, =, =>)
Brackets, parentheses, semicolons
Object properties and attributes
HTML/JSX tags
HTML/JSX attributes