Skip to main content
The Avala SDK is written in TypeScript and provides comprehensive type definitions for all API resources, making it easy to build type-safe applications.

Type safety benefits

The SDK provides full IntelliSense support and compile-time type checking:
import { Avala, Dataset } from '@avala-ai/sdk';

const avala = new Avala({ apiKey: 'your-api-key' });

// TypeScript knows the return type is Dataset
const dataset: Dataset = await avala.datasets.get('dataset-uid');

// IntelliSense suggests available properties
console.log(dataset.name);
console.log(dataset.itemCount);
console.log(dataset.createdAt);

Resource types

All resource types are exported from the SDK:
import type { Dataset } from '@avala-ai/sdk';

interface Dataset {
  uid: string;
  name: string;
  slug: string;
  itemCount: number;
  dataType: string | null;
  createdAt: string | null;
  updatedAt: string | null;
}

const dataset: Dataset = await avala.datasets.get('dataset-uid');

Pagination types

The SDK uses a generic CursorPage<T> type for paginated responses:
import type { CursorPage, Dataset } from '@avala-ai/sdk';

// Type is automatically inferred
const page = await avala.datasets.list();

// Or explicitly typed
const typedPage: CursorPage<Dataset> = await avala.datasets.list();

// Access typed items
for (const dataset of page.items) {
  // TypeScript knows this is a Dataset
  console.log(dataset.name);
}

CursorPage definition

The pagination type is defined as:
types.ts:65-70
export interface CursorPage<T> {
  items: T[];
  nextCursor: string | null;
  previousCursor: string | null;
  hasMore: boolean;
}
Use the generic CursorPage<T> type when building pagination utilities.

Configuration types

The client configuration is fully typed:
import { Avala, type AvalaConfig } from '@avala-ai/sdk';

const config: AvalaConfig = {
  apiKey: 'your-api-key',
  baseUrl: 'https://api.avala.ai/api/v1',
  timeout: 30000
};

const avala = new Avala(config);

AvalaConfig interface

types.ts:1-5
export interface AvalaConfig {
  apiKey?: string;
  baseUrl?: string;
  timeout?: number;
}
All configuration properties are optional. The SDK will use environment variables and defaults when not provided.

Error types

All error classes are fully typed with specific properties:
import { AvalaError } from '@avala-ai/sdk';

try {
  await avala.datasets.get('dataset-uid');
} catch (error) {
  if (error instanceof AvalaError) {
    // TypeScript knows these properties exist
    const status: number | undefined = error.statusCode;
    const body: unknown = error.body;
    const message: string = error.message;
  }
}

Generic request helpers

Build type-safe wrappers using TypeScript generics:
import type { Avala, CursorPage } from '@avala-ai/sdk';

async function fetchAll<T>(
  fetcher: (cursor: string | null) => Promise<CursorPage<T>>
): Promise<T[]> {
  const items: T[] = [];
  let cursor: string | null = null;
  
  do {
    const page = await fetcher(cursor);
    items.push(...page.items);
    cursor = page.nextCursor;
  } while (cursor !== null);
  
  return items;
}

// Usage with type inference
const datasets = await fetchAll((cursor) => 
  avala.datasets.list({ cursor })
);

// TypeScript knows datasets is Dataset[]
console.log(datasets[0].name);

Complex types

The SDK includes types for complex nested structures:
import type { Agent } from '@avala-ai/sdk';

interface Agent {
  uid: string;
  name: string;
  description: string | null;
  events: string[];
  callbackUrl: string | null;
  isActive: boolean;
  project: string | null;
  taskTypes: string[];
  createdAt: string | null;
  updatedAt: string | null;
}

const agent: Agent = await avala.agents.get('agent-uid');

// Type-safe array access
const firstEvent: string = agent.events[0];

Type guards

Create type-safe guards for runtime checks:
import type { Dataset, Project } from '@avala-ai/sdk';

function isDataset(resource: Dataset | Project): resource is Dataset {
  return 'itemCount' in resource;
}

function isProject(resource: Dataset | Project): resource is Project {
  return 'status' in resource;
}

// Usage
const resource: Dataset | Project = await getResource();

if (isDataset(resource)) {
  // TypeScript knows this is a Dataset
  console.log('Items:', resource.itemCount);
} else {
  // TypeScript knows this is a Project
  console.log('Status:', resource.status);
}

Null safety

Many properties are nullable in the API response:
import type { Dataset } from '@avala-ai/sdk';

const dataset: Dataset = await avala.datasets.get('dataset-uid');

// Handle nullable properties safely
const dataType: string = dataset.dataType ?? 'unknown';

if (dataset.createdAt) {
  const created = new Date(dataset.createdAt);
  console.log('Created:', created.toLocaleDateString());
}

// Optional chaining for nested nullable properties
const orgName = dataset.organization?.name ?? 'No organization';
Always check for null values before using properties marked as string | null or number | null.

Type-safe request builders

Build composable, type-safe request utilities:
import type { Avala, Dataset, Project } from '@avala-ai/sdk';

class TypeSafeClient {
  constructor(private avala: Avala) {}
  
  async getResource<T extends Dataset | Project>(
    type: 'dataset' | 'project',
    uid: string
  ): Promise<T> {
    if (type === 'dataset') {
      return await this.avala.datasets.get(uid) as T;
    } else {
      return await this.avala.projects.get(uid) as T;
    }
  }
  
  async listResources<T>(
    fetcher: () => Promise<CursorPage<T>>
  ): Promise<T[]> {
    const page = await fetcher();
    return page.items;
  }
}

const client = new TypeSafeClient(avala);

// Type is inferred as Dataset
const dataset = await client.getResource<Dataset>('dataset', 'uid');

// Type is inferred as Dataset[]
const datasets = await client.listResources(() => 
  avala.datasets.list()
);

Best practices

1

Enable strict mode

Use strict TypeScript settings in your tsconfig.json:
{
  "compilerOptions": {
    "strict": true,
    "strictNullChecks": true,
    "noImplicitAny": true,
    "esModuleInterop": true
  }
}
2

Import types explicitly

Use the type keyword for type-only imports:
import { Avala } from '@avala-ai/sdk';
import type { Dataset, Project, CursorPage } from '@avala-ai/sdk';
3

Use type inference

Let TypeScript infer types when possible:
// Good: Type is inferred
const dataset = await avala.datasets.get('uid');

// Unnecessary: Explicit type
const dataset: Dataset = await avala.datasets.get('uid');
4

Handle nullable properties

Always check for null values:
const dataset = await avala.datasets.get('uid');

// Use nullish coalescing
const dataType = dataset.dataType ?? 'unknown';

// Use optional chaining
const createdDate = dataset.createdAt
  ? new Date(dataset.createdAt)
  : null;
Leverage TypeScript’s IntelliSense in your IDE to discover available properties and methods.

Advanced patterns

Build sophisticated type-safe abstractions:
import type { Avala, CursorPage } from '@avala-ai/sdk';

type ResourceList<T> = () => Promise<CursorPage<T>>;
type ResourceGet<T> = (uid: string) => Promise<T>;

class Repository<T extends { uid: string }> {
  constructor(
    private list: ResourceList<T>,
    private get: ResourceGet<T>
  ) {}
  
  async findAll(): Promise<T[]> {
    const items: T[] = [];
    let cursor: string | null = null;
    
    do {
      const page = await this.list();
      items.push(...page.items);
      cursor = page.nextCursor;
    } while (cursor !== null);
    
    return items;
  }
  
  async findById(uid: string): Promise<T> {
    return await this.get(uid);
  }
  
  async findByIds(uids: string[]): Promise<T[]> {
    return await Promise.all(
      uids.map(uid => this.get(uid))
    );
  }
}

// Usage
const datasetRepo = new Repository(
  () => avala.datasets.list(),
  (uid) => avala.datasets.get(uid)
);

const allDatasets = await datasetRepo.findAll();
const dataset = await datasetRepo.findById('dataset-uid');
Created 4 Guides pages successfully

Build docs developers (and LLMs) love