TypeScript
The Easy React Native SDK is built with TypeScript and provides comprehensive type definitions for all APIs, components, and data structures.
Installation
TypeScript types are included with the package - no separate @types package is needed:
npm install @easylabs/react-native
Type Imports
Import types alongside your components:
import {
EasyProvider,
useEasy,
CardNumberElement,
} from "@easylabs/react-native";
// Import types
import type {
CreateCustomer,
CustomerData,
CreateCheckout,
CheckoutSessionData,
ApiResponse,
} from "@easylabs/react-native";
Component Types
EasyProvider
interface EasyProviderProps {
apiKey: string;
__dev?: boolean;
children: React.ReactNode;
}
Form Elements
interface CardNumberElementProps {
btRef: RefObject<ICardNumberElement>;
placeholder?: string;
style?: StyleProp<ViewStyle>;
editable?: boolean;
onFocus?: () => void;
onBlur?: () => void;
}
interface CardExpirationDateElementProps {
btRef: RefObject<ICardExpirationDateElement>;
placeholder?: string;
style?: StyleProp<ViewStyle>;
editable?: boolean;
onFocus?: () => void;
onBlur?: () => void;
}
interface CardVerificationCodeElementProps {
btRef: RefObject<ICardVerificationCodeElement>;
placeholder?: string;
style?: StyleProp<ViewStyle>;
editable?: boolean;
onFocus?: () => void;
onBlur?: () => void;
}
interface TextElementProps {
btRef: RefObject<ITextElement>;
placeholder?: string;
style?: StyleProp<ViewStyle>;
editable?: boolean;
onFocus?: () => void;
onBlur?: () => void;
}
API Types
Customer Types
interface CreateCustomer {
first_name: string;
last_name: string;
email: string;
phone?: string;
personal_address?: Address;
tags?: Record<string, unknown>;
}
interface CustomerData {
id: string;
first_name: string;
last_name: string;
email: string;
phone?: string;
personal_address?: Address;
tags?: Record<string, unknown>;
created_at: string;
updated_at: string;
}
Checkout Types
type CreateCheckout =
| CreateCheckoutNewCustomer
| CreateCheckoutExistingCustomer;
interface CreateCheckoutNewCustomer {
customer_creation: true;
customer_details: CreateCustomer;
source: PaymentSource;
line_items: LineItem[];
metadata?: Record<string, unknown>;
}
interface CreateCheckoutExistingCustomer {
customer_creation: false;
identity_id: string; // Customer ID
source: string | PaymentSource; // Payment instrument ID or new payment source
line_items: LineItem[];
metadata?: Record<string, unknown>;
}
interface CheckoutSessionData {
customer: CustomerData;
payment_instrument: PaymentInstrumentData;
transfer: TransferData;
order: OrderData;
}
Payment Types
type PaymentSource = PaymentCardParams | BankAccountParams;
interface PaymentCardParams {
type: "PAYMENT_CARD";
cardNumberElement: RefObject<ICardNumberElement>;
cardExpirationDateElement: RefObject<ICardExpirationDateElement>;
cardVerificationCodeElement: RefObject<ICardVerificationCodeElement>;
name?: string;
address?: Address;
}
interface BankAccountParams {
type: "BANK_ACCOUNT";
accountType: "CHECKING" | "SAVINGS";
routingElement: RefObject<ITextElement>;
accountElement: RefObject<ITextElement>;
name?: string;
}
Product Types
interface CreateProduct {
name: string;
description?: string;
active?: boolean;
metadata?: Record<string, unknown>;
}
interface ProductData {
id: string;
name: string;
description?: string;
active: boolean;
metadata?: Record<string, unknown>;
created_at: string;
updated_at: string;
}
interface CreatePrice {
product_id: string;
unit_amount: number; // Amount in cents
currency: string;
recurring?: {
interval: "day" | "week" | "month" | "year";
interval_count: number;
};
active?: boolean;
description?: string;
metadata?: Record<string, unknown>;
}
interface PriceData {
id: string;
product_id: string;
unit_amount: number;
currency: string;
recurring?: {
interval: string;
interval_count: number;
};
active: boolean;
description?: string;
metadata?: Record<string, unknown>;
created_at: string;
updated_at: string;
}
Response Types
interface ApiResponse<T> {
data: T;
status: number;
}
Usage Examples
Typed Customer Creation
import { useEasy } from "@easylabs/react-native";
import type {
CreateCustomer,
CustomerData,
ApiResponse,
} from "@easylabs/react-native";
import { Button, Alert } from "react-native";
function CreateCustomerButton() {
const { createCustomer } = useEasy();
const handleCreate = async () => {
const customerData: CreateCustomer = {
first_name: "John",
last_name: "Doe",
email: "[email protected]",
phone: "+1234567890",
personal_address: {
line1: "123 Main St",
city: "Anytown",
state: "CA",
postal_code: "12345",
country: "US",
},
};
try {
const response: ApiResponse<CustomerData> =
await createCustomer(customerData);
Alert.alert("Success", `Customer ID: ${response.data.id}`);
} catch (error) {
Alert.alert("Error", error.message);
}
};
return <Button title="Create Customer" onPress={handleCreate} />;
}
Typed Checkout
import { useEasy, CardNumberElement } from "@easylabs/react-native";
import type {
CreateCheckout,
CheckoutSessionData,
ApiResponse,
} from "@easylabs/react-native";
import { useRef, useState } from "react";
import { View, Button, Alert } from "react-native";
function CheckoutScreen() {
const { checkout } = useEasy();
const cardNumberRef = useRef(null);
const expiryRef = useRef(null);
const cvcRef = useRef(null);
const [loading, setLoading] = useState(false);
const handleCheckout = async () => {
setLoading(true);
const checkoutData: CreateCheckout = {
customer_creation: true,
customer_details: {
first_name: "Jane",
last_name: "Smith",
email: "[email protected]",
},
source: {
type: "PAYMENT_CARD",
cardNumberElement: cardNumberRef,
cardExpirationDateElement: expiryRef,
cardVerificationCodeElement: cvcRef,
name: "Jane Smith",
},
line_items: [{ price_id: "price_123", quantity: 1 }],
};
try {
const response: ApiResponse<CheckoutSessionData> =
await checkout(checkoutData);
Alert.alert(
"Success",
`Order ID: ${response.data.order.id}\nTransfer ID: ${response.data.transfer.id}`,
);
} catch (error) {
Alert.alert("Error", error.message);
} finally {
setLoading(false);
}
};
return (
<View>
{/* Form elements */}
<Button
title={loading ? "Processing..." : "Complete Purchase"}
onPress={handleCheckout}
disabled={loading}
/>
</View>
);
}
Typed Product Management
import { useEasy } from "@easylabs/react-native";
import type {
CreateProduct,
ProductData,
ApiResponse,
} from "@easylabs/react-native";
import { useState, useEffect } from "react";
import { FlatList, Text, View } from "react-native";
function ProductList() {
const { getProducts } = useEasy();
const [products, setProducts] = useState<ProductData[]>([]);
useEffect(() => {
loadProducts();
}, []);
const loadProducts = async () => {
try {
const response: ApiResponse<ProductData[]> = await getProducts({
limit: 20,
});
setProducts(response.data);
} catch (error) {
console.error("Failed to load products:", error);
}
};
return (
<FlatList
data={products}
keyExtractor={(item: ProductData) => item.id}
renderItem={({ item }) => (
<View>
<Text>{item.name}</Text>
<Text>{item.description}</Text>
<Text>{item.active ? "Active" : "Inactive"}</Text>
</View>
)}
/>
);
}
Generic Type Parameters
The SDK uses generic type parameters for flexible typing:
// Single item response
ApiResponse<CustomerData>;
// Array response
ApiResponse<ProductData[]>;
// Subscription response
ApiResponse<SubscriptionData>;
Type Guards
Use type guards to narrow union types:
import type { CreateCheckout } from "@easylabs/react-native";
function isNewCustomerCheckout(
checkout: CreateCheckout,
): checkout is CreateCheckoutNewCustomer {
return checkout.customer_creation === true;
}
// Usage
if (isNewCustomerCheckout(checkoutData)) {
// TypeScript knows this is CreateCheckoutNewCustomer
console.log(checkoutData.customer_details.email);
}
Utility Types
Use TypeScript utility types with SDK types:
import type { CreateCustomer, CustomerData } from "@easylabs/react-native";
// Partial update
type UpdateCustomer = Partial<CreateCustomer>;
// Pick specific fields
type CustomerSummary = Pick<CustomerData, "id" | "first_name" | "last_name">;
// Omit fields
type CustomerWithoutDates = Omit<CustomerData, "created_at" | "updated_at">;
// Make fields required
type RequiredCustomer = Required<CreateCustomer>;
Type Inference
Let TypeScript infer types when possible:
const { createCustomer, getProducts } = useEasy();
// Return types are automatically inferred
const customerResponse = await createCustomer({...}); // ApiResponse<CustomerData>
const productsResponse = await getProducts(); // ApiResponse<ProductData[]>
// Extract data with inferred types
const customer = customerResponse.data; // CustomerData
const products = productsResponse.data; // ProductData[]
Best Practices
1. Always Import Types
// ✅ Good
import type { CreateCustomer, CustomerData } from "@easylabs/react-native";
// ❌ Avoid
import { CreateCustomer, CustomerData } from "@easylabs/react-native";
2. Use Strict Mode
Enable strict mode in tsconfig.json:
{
"compilerOptions": {
"strict": true,
"strictNullChecks": true,
"strictFunctionTypes": true
}
}
3. Type Function Parameters
// ✅ Good
const handleCreate = async (data: CreateCustomer) => {
await createCustomer(data);
};
// ❌ Avoid
const handleCreate = async (data: any) => {
await createCustomer(data);
};
4. Type State Variables
// ✅ Good
const [products, setProducts] = useState<ProductData[]>([]);
const [loading, setLoading] = useState<boolean>(false);
// ❌ Avoid
const [products, setProducts] = useState([]);
const [loading, setLoading] = useState(false);