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:
// Import types from the SDK's auto-generated definitions
import type { 
  GetProductDetailContent,
  GetCartContent, 
  GetOrderDetailContent,
  GetUserDetailContent,
  ApiResult 
} from '@commercengine/storefront-sdk';

The { data, error } Pattern

Every API operation returns a type-safe object with data and error properties:
// Type signature automatically inferred from OpenAPI spec
const { data, error } = await client.catalog.getProduct('product-id');

if (data) {
  // TypeScript knows data is GetProductDetailContent
  const product = data.content;
  console.log(product.id);           // βœ… string
  console.log(product.name);         // βœ… string
  console.log(product.slug);         // βœ… string
  console.log(product.description);  // βœ… string
} else if (error) {
  // TypeScript knows error is ApiErrorResponse
  console.log(error.message); // βœ… string
  console.log(error.code);    // βœ… string
}

IntelliSense in Action

Method Parameters

Complete autocomplete for all API parameters with OpenAPI-generated types:
// IntelliSense shows all available options from OpenAPI spec
const { data: productsData, error } = await client.catalog.listProducts({
  limit: 20,                    // βœ… number | undefined
  category_id: 'electronics',   // βœ… string | undefined
  sort_by: 'name',             // βœ… string | undefined  
  min_price: 100,              // βœ… number | undefined
  max_price: 500               // βœ… number | undefined
});

Response Data Access

Full type safety when accessing response data:
if (productsData) {
  const productList = productsData.content;
  
  productList.forEach(product => {
    // Full IntelliSense for auto-generated Product schema
    product.id;              // βœ… string
    product.name;            // βœ… string  
    product.slug;            // βœ… string
    product.description;     // βœ… string
    product.short_description; // βœ… string | null
    product.is_active;       // βœ… boolean
    
    // TypeScript prevents accessing non-existent properties
    product.nonExistent;     // ❌ Compile error
  });
}

Cart Operations

Type-safe cart management with correct API structure:
// Creating cart with typed item structure from OpenAPI
const { data, error } = await client.cart.createCart({
  items: [{
    product_id: 'prod_123',    // βœ… string (required)
    variant_id: null,          // βœ… string | null (required)
    quantity: 2                // βœ… number (required)
  }]
});

if (data) {
  const cartData = data.content;
  // Cart object with full type safety from OpenAPI schema
  cartData.id;                    // βœ… string
  cartData.cart_items;            // βœ… CartItem[]
  cartData.grand_total;           // βœ… number
  cartData.currency;              // βœ… string
  cartData.shipping_address;      // βœ… object | null
}

Advanced Type Features

Discriminated Unions

Type-safe handling of different response states:
// The { data, error } pattern with proper error handling
const { data, error } = await client.auth.loginWithEmail({ 
  email: '[email protected]' 
});

if (data) {
  // TypeScript knows data contains the success response
  const loginData = data.content;
  loginData.otp_token;  // βœ… string
  loginData.otp_action; // βœ… string
} else if (error) {
  // TypeScript knows error contains error information
  error.message; // βœ… string
  error.code;    // βœ… string
}

Generic Type Constraints

Type-safe configuration with OpenAPI-generated interfaces:
// TokenStorage interface is properly typed
interface TokenStorage {
  getAccessToken(): Promise<string | null>;
  setAccessToken(token: string): Promise<void>;
  getRefreshToken(): Promise<string | null>;
  setRefreshToken(token: string): Promise<void>;
  clearTokens(): Promise<void>;
}

// Implementation must satisfy interface
class CustomTokenStorage implements TokenStorage {
  async getAccessToken(): Promise<string | null> {
    // Implementation must return correct type
    return localStorage.getItem('access_token');
  }
  
  // ... other methods with type safety
}

Framework Integration Types

React Hook Types

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

Component Props

// Type-safe component props using OpenAPI types
interface ProductCardProps {
  product: GetProductDetailContent;               // βœ… 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.description}</p>     {/* βœ… Known to be string */}
      
      <button onClick={() => onAddToCart(product.id, null)}>
        Add to Cart
      </button>
    </div>
  );
};

Type Utilities

Exported Utility Types

// Import specific types for custom implementations
import type {
  GetProductDetailContent,
  GetCartContent,
  GetOrderDetailContent,
  GetUserDetailContent,
  ApiResult,
  ListProductsQuery,
  CreateCartBody
} from '@commercengine/storefront-sdk';

// Use in your application
interface AppState {
  currentUser: GetUserDetailContent | null;
  cart: GetCartContent | null;
  products: GetProductDetailContent[];
}

Type Guards

// Type guards for runtime type checking
function isProductResult(
  result: ApiResult<any>
): result is { data: { content: GetProductDetailContent }; error: null } {
  return result.data && 
         result.data.content && 
         typeof result.data.content.id === 'string';
}

// Usage with type safety
const result = await client.catalog.getProduct('product-id');
if (isProductResult(result)) {
  // TypeScript knows result.data.content is GetProductDetailContent
  console.log(result.data.content.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: invalid property in request body
await client.cart.createCart({
  items: [{ 
    product_id: 'id', 
    variant_id: null, 
    qty: 2  // Should be 'quantity'
  }]
});

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

// ❌ Compile error: accessing wrong property
if (result.data) {
  console.log(result.data.invalidProperty); // Property doesn't exist
}

Type Safety vs Direct API

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

if (result.data) {
  // βœ… TypeScript knows exact structure from OpenAPI schema
  const product = result.data.content;
  console.log(product.name);         // βœ… Known to be string
  console.log(product.id);           // βœ… Known to be string
  console.log(product.is_active);    // βœ… Known to be boolean
} else if (result.error) {
  // βœ… Typed error handling
  console.error(result.error.message); // βœ… Known error structure
}

Best Practices

Migration Benefits

When migrating from direct API calls:

Catch Errors Early

Find API usage errors during development, not production

Always Current Documentation

Types are auto-generated from OpenAPI spec and always up-to-date

Faster Development

IntelliSense speeds up development with accurate 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. The examples above use the real type names and property structures from the Commerce Engine API.