npm package

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

TypeScript
// Before: Brittle string-based paths
<Image source={require('../../../assets/toast/info.png')} />
<LottieView source={require('../../utils/loading.json')} />

With rn-typed-assets

TypeScript
// 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

Asset Directorysrc/assets/
ScanRecursive file discovery
NormalizeGenerate camelCase keys
Emitassets.gen.ts + manifest
ImportType-safe references
1

Scan

For each enabled asset type, recursively list files under the configured rootDir.

2

Normalize

Convert each filename to a stable camelCase key. Handle edge cases like numeric prefixes and collisions.

3

Build Registry Tree

Assemble a nested object tree from path segments. Detect and resolve branch/leaf collisions automatically.

4

Emit

Write assets.gen.ts (typed as const object) and assets.manifest.json (stable index of every key ↔ file mapping).

Example Asset Tree

Bash
src/assets/
  toast/
    info.png
    warning.png
  coupang/
    harini-cry.png
  lottie/
    loading.json
  svg/
    logo.svg

Key Normalization Rules

FilenameGenerated Key
harini-cry.pnghariniCry
camera_guide.pngcameraGuide
Info-Filled.pnginfoFilled
1.pngn1 (numeric prefix → n)
point.png alongside point/ dirpointAsset (collision)

Generated Output

assets.gen.tsTypeScript
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?

Compile-time safety: Missing assets fail at generation, not runtime
Autocomplete: IDE support for all your assets
Refactoring: Rename files and let the tool update references
Clean codebase: Find and remove unused assets automatically
01

Install the package

Add rn-typed-assets as a dev dependency. TypeScript must be available in your project (most RN projects already have it).

Bash
npm install --save-dev rn-typed-assets
02

Add scripts to package.json

Configure convenient npm scripts for generation, organization, and auditing.

package.jsonJSON
{
  "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"
  }
}
03

Run the generator

Execute the generate command to create assets.gen.ts and assets.manifest.json in src/generated/.

Bash
npm run assets:generate
04

Import and use

Import the typed registry and use named constants instead of require() paths.

TypeScript
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} />
05

Audit for unused assets

Run the audit command to find and optionally remove unused assets from your codebase.

Bash
npm run assets:audit          # report unused entries
npm run assets:audit -- --fix # delete unused files and regenerate

CLI Reference

Three commands to generate, organize, and audit your assets.

generate

Scan asset directories and emit assets.gen.ts + assets.manifest.json.

Options

FlagDescriptionDefault
--types <types>Comma-separated asset typesimage,svg,lottie
--inplaceRewrite source files after regenfalse
--root <path>Project root directorycwd
--config <path>Path to config file./rn-typed-assets.config.js

Examples

Bash
rn-typed-assets generate
rn-typed-assets generate --inplace
rn-typed-assets generate --types=image,lottie

organize

Move asset files into canonical subdirectories, then regenerate and rewrite sources.

Creates: images/, svgs/, lotties/ subdirectories

Options

FlagDescriptionDefault
<assetsDir>Path to the asset root to organize(required)
--types <types>Asset types to moveimage,svg,lottie

Examples

Bash
rn-typed-assets organize src/assets

audit

Compare manifest against actual source-file usages.

Options

FlagDescriptionDefault
--types <types>Asset types to auditimage,svg,lottie
--fixDelete unused files and regeneratefalse

Examples

Bash
rn-typed-assets audit
rn-typed-assets audit --fix
rn-typed-assets audit --types=image

Configuration

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.

rn-typed-assets.config.jsJavaScript
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.

JavaScript
// 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

outputDir

Directory for generated files

sourceRoots

Files/dirs scanned by audit command

rootDir

Asset scan root for each type

extensions

File extensions to include

exportName

Name of exported constant

typeImport / inlineType

TypeScript 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.

YAML
# .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.

Bash
# .husky/pre-commit
npm run assets:generate
git add src/generated/assets.gen.ts src/generated/assets.manifest.json
Syntax Highlighting

Beautiful Code Highlighting for Every Language

Professional syntax highlighting powered by Shiki with support for 25+ programming languages. Optimized for readability and accessibility.

example.tsTypeScript
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

keyword

Language keywords (const, function, if, return)

string

String literals and template strings

comment

Comments and documentation

function

Function names and method calls

variable

Variables and identifiers

number

Numeric literals

type

Type annotations and interfaces

operator

Operators (+, -, =, =>)

punctuation

Brackets, parentheses, semicolons

property

Object properties and attributes

tag

HTML/JSX tags

attribute

HTML/JSX attributes

Supported Languages (24+)

TypeScriptJavaScriptHTMLCSSJSONSwiftKotlinJavaPythonGoRustCC++BashShellYAMLTOMLSQLGraphQLMarkdownXMLDockerfileDiffPlain Text