TypeScript

The SDK is fully typed and supports type-safe component props through TypeScript declaration merging.

Type-Safe Component Props

Register your component props for type-safe usage throughout your app:

types/dpage.d.ts
declare module '@dpage-ai/react-native-dpage' {
  interface ComponentPropsMap {
    ProductCard: { productId: string; showPrice?: boolean };
    UserProfile: { userId: string };
    CheckoutForm: { cartId: string; onComplete: () => void };
    PromoBanner: { campaignId?: string };
  }
}

Now DynamicComponent and useDynamicComponent will enforce the correct props:

TSX
// Type-safe! ✓
<DynamicComponent
  name="ProductCard"
  data={{ productId: '123' }}
/>

// TypeScript error: missing 'productId'
<DynamicComponent
  name="ProductCard"
  data={{ showPrice: true }}  // Error!
/>

// TypeScript error: wrong prop type
<DynamicComponent
  name="ProductCard"
  data={{ productId: 123 }}  // Error! productId should be string
/>

Hook Type Safety

The useDynamicComponent hook also benefits from the type declarations:

TSX
function MyScreen() {
  const { Component, loading, error } = useDynamicComponent('ProductCard');

  if (loading || !Component) return null;

  // Component props are inferred from ComponentPropsMap
  return (
    <Component
      productId="123"      // ✓ Required
      showPrice={true}     // ✓ Optional
    />
  );
}

Configuration Types

TSX
import type { DPageConfig } from '@dpage-ai/react-native-dpage';

const config: DPageConfig = {
  projectId: 'my-project',
  apiToken: 'dpage_live_xxx',
  fetch: {
    timeout: 10000,
    enabled: true,
  },
  cache: {
    ttl: 3600000,
    enabled: true,
  },
  logLevel: 'warn',
};

initDPage(config);

Event Handler Types

TSX
import { dpage } from '@dpage-ai/react-native-dpage';
import type {
  FetchStartEvent,
  FetchSuccessEvent,
  FetchErrorEvent,
  CacheEvent,
} from '@dpage-ai/react-native-dpage';

dpage.on('fetchStart', (e: FetchStartEvent) => {
  console.log(e.componentKey);
});

dpage.on('fetchSuccess', (e: FetchSuccessEvent) => {
  console.log(`${e.componentKey} loaded in ${e.durationMs}ms`);
});

dpage.on('fetchError', (e: FetchErrorEvent) => {
  console.error(e.error);
});

dpage.on('cacheHit', (e: CacheEvent) => {
  console.log(`Cache hit: ${e.componentKey}`);
});

Error Types

TSX
import {
  HttpError,
  FetchTimeoutError,
} from '@dpage-ai/react-native-dpage';

try {
  await refreshComponent('MyComponent');
} catch (error: unknown) {
  if (error instanceof HttpError) {
    // Type-safe access to HttpError properties
    console.log(`Status: ${error.status}`);
    console.log(`Status Text: ${error.statusText}`);
  } else if (error instanceof FetchTimeoutError) {
    // Type-safe access to FetchTimeoutError properties
    console.log(error.message);
  }
}

Custom Runtime Deps Types

deps.dpage.ts
import axios from 'axios';
import { format } from 'date-fns';
import CustomButton from './src/components/CustomButton';

// Explicitly type your dependencies
const apiDeps = {
  axios,
  format,
} as const;

const componentDeps = {
  CustomButton,
} as const;

// Type the export
export const customRuntimeDeps = {
  ...apiDeps,
  ...componentDeps,
} as const;

// Optional: Export the type for use elsewhere
export type CustomDeps = typeof customRuntimeDeps;

Strict Mode

The SDK is designed to work with TypeScript strict mode enabled. Ensure your tsconfig.json includes:

tsconfig.json
{
  "compilerOptions": {
    "strict": true,
    "strictNullChecks": true,
    "noImplicitAny": true
  }
}

Generic Components

Create generic wrapper components with proper typing:

TSX
import { DynamicComponent, ComponentPropsMap } from '@dpage-ai/react-native-dpage';

// Generic wrapper with loading skeleton
function DynamicWithSkeleton<K extends keyof ComponentPropsMap>({
  name,
  data,
  skeleton,
}: {
  name: K;
  data?: ComponentPropsMap[K];
  skeleton: React.ReactNode;
}) {
  return (
    <DynamicComponent
      name={name}
      data={data}
      renderLoading={() => skeleton}
    />
  );
}

// Usage - fully typed
<DynamicWithSkeleton
  name="ProductCard"
  data={{ productId: '123' }}
  skeleton={<ProductCardSkeleton />}
/>

Declaration File Location

Create your type declarations in one of these locations:

  • types/dpage.d.ts (recommended)
  • src/types/dpage.d.ts
  • @types/dpage.d.ts

Ensure the file is included in your tsconfig.json:

tsconfig.json
{
  "compilerOptions": {
    "typeRoots": ["./node_modules/@types", "./types"]
  },
  "include": ["src/**/*", "types/**/*"]
}

Best Practices

Define all component props

Add every dynamic component to ComponentPropsMap for full type safety.

Use strict mode

Enable TypeScript strict mode for best type checking.

Type custom deps

Use 'as const' for runtime deps to preserve exact types.

Handle null Component

Always check Component is not null before rendering.