The SDK provides 100% type safety with auto-generated types from OpenAPI specifications, complete IntelliSense support, and compile-time error prevention.

Why Type Safety Matters

IntelliSense Support

Complete autocomplete for all API methods, parameters, and response data

Compile-time Checking

Catch errors during development, not at runtime

Self-Documenting Code

Types serve as always up-to-date documentation

Refactoring Safety

Confidently refactor with IDE support for finding all usages

Auto-Generated Types

All types are automatically generated from the OpenAPI specification, ensuring they’re always in sync with the API:

// Types are generated from OpenAPI spec and always current
import type { 
  Product, 
  Cart, 
  Order, 
  Customer,
  ApiResult 
} from '@commercengine/storefront-sdk';

ApiResult Pattern

Every API operation returns a type-safe ApiResult<T>:

// Type signature automatically inferred
const productResult: ApiResult<Product> = await client.catalog.getProduct('id');

if (productResult.success) {
  // TypeScript knows productResult.data is of type Product
  console.log(productResult.data.name); // βœ… string
  console.log(productResult.data.selling_price); // βœ… number
  console.log(productResult.data.images); // βœ… ProductImage[]
} else {
  // TypeScript knows productResult.error is ApiErrorResponse
  console.log(productResult.error.code); // βœ… string
  console.log(productResult.error.message); // βœ… string
}

IntelliSense in Action

Method Parameters

Complete autocomplete for all API parameters:

// IntelliSense shows all available options
const products = await client.catalog.listProducts({
  limit: 20,                    // βœ… number
  category_id: 'electronics',   // βœ… string | undefined
  sort_by: 'price_low_to_high', // βœ… Specific string literals
  min_price: 100,               // βœ… number | undefined
  max_price: 500                // βœ… number | undefined
});

Response Data Access

Full type safety when accessing response data:

if (products.success) {
  products.data.forEach(product => {
    // Full IntelliSense for Product interface
    product.id;              // βœ… string
    product.name;            // βœ… string
    product.selling_price;   // βœ… number
    product.listing_price;   // βœ… number
    product.images;          // βœ… ProductImage[]
    product.category;        // βœ… Category
    product.variants;        // βœ… ProductVariant[]
    
    // TypeScript prevents accessing non-existent properties
    product.nonExistent;     // ❌ Compile error
  });
}

Cart Operations

Type-safe cart management:

// Creating cart with typed item structure
const cart = await client.cart.createCart({
  items: [{
    product_id: 'prod_123',    // βœ… string (required)
    variant_id: null,          // βœ… string | null (required)
    quantity: 2                // βœ… number (required)
  }]
});

if (cart.success) {
  // Cart object with full type safety
  cart.data.id;                    // βœ… string
  cart.data.cart_items;            // βœ… CartItem[]
  cart.data.grand_total;           // βœ… number
  cart.data.currency;              // βœ… Currency
  cart.data.shipping_address;      // βœ… CustomerAddress | null
}

Advanced Type Features

Discriminated Unions

Type-safe handling of different response states:

// ApiResult is a discriminated union
type ApiResult<T> = 
  | { success: true; data: T }
  | { success: false; error: ApiErrorResponse };

// TypeScript narrows types based on success field
const result = await client.auth.loginWithEmail({ email: '[email protected]' });

if (result.success) {
  // TypeScript knows result.data exists and is LoginResponse
  result.data.otp_token;  // βœ… string
  result.error;           // ❌ TypeScript error: doesn't exist
} else {
  // TypeScript knows result.error exists and is ApiErrorResponse  
  result.error.code;      // βœ… string
  result.data;            // ❌ TypeScript error: doesn't exist
}

Generic Type Constraints

Type-safe configuration with constraints:

// TokenStorage interface with generic constraints
interface TokenStorage<T = StoredTokens> {
  getTokens(): Promise<T | null>;
  setTokens(tokens: T): Promise<void>;
  clearTokens(): Promise<void>;
}

// Implementation must satisfy interface
class CustomTokenStorage implements TokenStorage {
  async getTokens(): Promise<StoredTokens | null> {
    // Implementation must return correct type
    return { accessToken: '...', refreshToken: '...' };
  }
  
  // ... other methods with type safety
}

Framework Integration Types

React Hook Types

// Custom hook with full type safety
function useProducts(categoryId?: string): {
  products: Product[] | null;
  loading: boolean;
  error: ApiErrorResponse | null;
} {
  const [products, setProducts] = useState<Product[] | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<ApiErrorResponse | null>(null);
  
  useEffect(() => {
    async function fetchProducts() {
      const result = await client.catalog.listProducts({
        category_id: categoryId,
        limit: 50
      });
      
      if (result.success) {
        setProducts(result.data);     // βœ… Type-safe assignment
      } else {
        setError(result.error);       // βœ… Type-safe error handling
      }
      
      setLoading(false);
    }
    
    fetchProducts();
  }, [categoryId]);
  
  return { products, loading, error };
}

Component Props

// Type-safe component props
interface ProductCardProps {
  product: Product;               // βœ… Generated Product type
  onAddToCart: (productId: string, variantId: string | null) => void;
}

const ProductCard: React.FC<ProductCardProps> = ({ product, onAddToCart }) => {
  return (
    <div>
      <h3>{product.name}</h3>          {/* βœ… Type-safe access */}
      <p>${product.selling_price}</p>  {/* βœ… Known to be number */}
      
      <button onClick={() => onAddToCart(product.id, null)}>
        Add to Cart
      </button>
    </div>
  );
};

Type Utilities

Exported Utility Types

// Import specific types for custom implementations
import type {
  Product,
  Cart,
  CartItem,
  Order,
  Customer,
  ApiResult,
  ApiErrorResponse,
  StoredTokens,
  CommerceEngineConfig
} from '@commercengine/storefront-sdk';

// Use in your application
interface AppState {
  currentUser: Customer | null;
  cart: Cart | null;
  products: Product[];
}

Type Guards

// Type guards for runtime type checking
function isProduct(item: unknown): item is Product {
  return typeof item === 'object' && 
         item !== null && 
         'id' in item && 
         'name' in item;
}

// Usage with type safety
const data: unknown = await fetch('/some-endpoint');
if (isProduct(data)) {
  // TypeScript knows data is Product
  console.log(data.name);
}

Development Experience

IDE Integration

The SDK works seamlessly with popular IDEs:

  • VSCode: Full IntelliSense, error squiggles, auto-imports
  • WebStorm: Complete type information, refactoring support
  • Vim/Neovim: TypeScript LSP provides full type information

Compile-Time Validation

// These errors are caught at compile time, not runtime:

// ❌ Compile error: quantity must be number
await client.cart.createCart({
  items: [{ product_id: 'id', variant_id: null, quantity: '2' }]
});

// ❌ Compile error: invalid property name
const result = await client.catalog.listProducts({
  limite: 20  // Should be 'limit'
});

// ❌ Compile error: accessing wrong property
if (result.success) {
  console.log(result.data.invalidProperty);
}

Type Safety vs Direct API

// Full type safety and IntelliSense
const result = await client.catalog.getProduct('product-id');

if (result.success) {
  // βœ… TypeScript knows exact structure
  const product: Product = result.data;
  console.log(product.name);           // βœ… Known to be string
  console.log(product.selling_price);  // βœ… Known to be number
  console.log(product.images[0].url);  // βœ… Safe array access
} else {
  // βœ… Typed error handling
  console.error(result.error.code);    // βœ… Known error structure
}

Best Practices

Migration Benefits

When migrating from direct API calls:

Catch Errors Early

Find API usage errors during development, not production

Better Documentation

Types serve as always-current API documentation

Faster Development

IntelliSense speeds up development with autocomplete

Confident Refactoring

Change APIs with confidence using IDE refactoring tools

All SDK types are automatically generated from the OpenAPI specification, ensuring they’re always accurate and up-to-date with the actual API responses.