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
| Scenario | Use /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
windowdefensively. 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
schemaspackage canimport type { CarStatus }from/typeswithout 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: notimport type), TypeScript will let you (the schema is in the source), but at runtime it'll beundefined. Use the main entry for schemas:import { CarStatusSchema } from '@i99dash/sdk-types'(the wire-types package). - No re-exports.
/typesis a flat list; there's no@i99dash/sdk/types/carsubpath. Keeps the bundle audit simple. enumwould be a runtime. None of the type-only exports areenums — they're string-literal unions or interfaces. Future schema additions follow the same rule.
Related
- API reference — full export listing with runtime counterparts.
- Best practices — Imports — convention for the rest of your imports.