i99dash docs
Guides

Type-only imports

When to use `@i99dash/sdk/types` vs the main entry, and why both exist.

Both runtime packages publish a type-only subpath. Use it when you need a SHAPE but never a RUNTIME.

// Pulls the type only — emits zero JavaScript.
import type { MiniAppContext, CarStatus } from '@i99dash/sdk/types';
import type { CommandTemplate } from '@i99dash/admin-sdk/types';

The dist artifact for /types contains a single empty .js file (literally 40 bytes after minification — the ESM module marker). Tree-shakers drop it entirely.

When you actually want this

ScenarioUse /types?
Server-rendered page that types a prop as MiniAppContext✓ Yes
Shared schema package referenced by both mini-app + backend✓ Yes
Pure-TypeScript helper that maps a CarStatus to a UI tree✓ Yes (works in Node, web worker, deno)
Anything that calls MiniAppClient.fromWindow()✗ No — needs the runtime
Tests that exercise the Bridge interface✗ No — needs the runtime for withBridge

Why it exists

  • SSR cleanliness. Importing the runtime SDK from a Next.js server component pulls a dependency that calls window defensively. No actual error, but webpack lights up the SSR-incompatibility warning. import type from '/types' skips the whole branch.
  • Bundle visibility. A consumer who sees import type { X } from '@i99dash/sdk/types' knows by inspection that this code path doesn't add bytes to the runtime bundle. With a regular type-only import from '@i99dash/sdk', you have to trust the bundler is doing dead-code-elimination correctly.
  • Cross-package use without duplication. Your shared schemas package can import type { CarStatus } from /types without pulling the rest of the SDK into its own dependency tree.

What's exported from /types

Same wire types you'd get from the main entry, plus the type aliases that go with them. Names match @i99dash/sdk exactly.

@i99dash/sdk/types:

type MiniAppContext;
type CallApiRequest;
type CallApiResponse<T = unknown>;
type ApiMethod;             // 'GET' (v1)

type CarStatus;
type CarStatusStaleness;    // 'fresh' | 'stale' | 'very_stale'
type CarConnectionState;    // 'connected' | 'disconnected'
type CarDoors;
type CarDoorState;          // 'open' | 'closed'

type CallOptions;
type SDKErrorCode;
type Bridge;
type CarStatusBridge;
type HostBridgeApi;
type WindowWithHost;

type CarStatusListener;
type CarConnectionListener;

@i99dash/admin-sdk/types:

type AdminClientContext;
type AdminClientOptions;
type InvokeOptions;

type AdminBridge;
type AdminExecRequest;

type AdminOpResponse<T = unknown>;
type CapabilityResponse;
type CatalogSnapshot;
type CommandTemplate;
type ParamRule;

Caveats

  • No runtime symbols are exported. If you write import { CarStatusSchema } from '@i99dash/sdk/types' (note: not import type), TypeScript will let you (the schema is in the source), but at runtime it'll be undefined. Use the main entry for schemas: import { CarStatusSchema } from '@i99dash/sdk-types' (the wire-types package).
  • No re-exports. /types is a flat list; there's no @i99dash/sdk/types/car subpath. Keeps the bundle audit simple.
  • enum would be a runtime. None of the type-only exports are enums — they're string-literal unions or interfaces. Future schema additions follow the same rule.

On this page