Skip to main content

TypeScript Support

Lovrabet SDK provides complete TypeScript support, including type definitions, type inference, and compile-time error detection.

Prerequisites

Before starting, please ensure you have completed SDK Configuration. We recommend using CLI automatic configuration generation.

Type Imports

import {
createClient,
registerModels,
// Configuration types
type ClientConfig,
type ModelsConfig,
type ModelConfig,
type Environment,
// Query types
type ListParams,
type ListResponse,
type FilterParams,
type WhereCondition,
type FieldCondition,
type ConditionOperator,
// Sort types
type SortList,
SortOrder,
// Select option types
type SelectOption,
type SelectOptionsParams,
// Model types
type BaseModelMethods,
type LovrabetClient,
} from "@lovrabet/sdk";

Environment and Basic Types

Environment

// Environment type
type Environment = "online" | "daily";

SortOrder Enum

// Sort direction
enum SortOrder {
ASC = "asc", // Ascending
DESC = "desc", // Descending
}

// Sort configuration (array format)
type SortList = Record<string, SortOrder>[];

// Usage example
const sortList: SortList = [
{ id: SortOrder.DESC },
{ name: SortOrder.ASC },
];

Configuration Types

ModelConfig

// Single model configuration
interface ModelConfig {
/** Table name (required) */
tableName: string;
/** Dataset code (required, unique identifier) */
datasetCode: string;
/** Display name (optional, for UI display) */
name?: string;
/** Alias (optional, for client.models.alias access) */
alias?: string;
/** Database name (optional, for distinguishing tables with the same name in different databases) */
dbName?: string;
}

ModelsConfig

// Model configuration collection
interface ModelsConfig {
/** Application code */
appCode: string;
/**
* Model configuration (supports two formats)
* - Array format (recommended)
* - Object format (backward compatible)
*/
models: ModelConfig[] | Record<string, ModelConfig>;
}

// Array format (recommended)
const config: ModelsConfig = {
appCode: "my-app",
models: [
{ datasetCode: "xxx", tableName: "users", alias: "users" },
{ datasetCode: "yyy", tableName: "orders", alias: "orders" },
],
};

// Object format (backward compatible, key used as default alias)
const legacyConfig: ModelsConfig = {
appCode: "my-app",
models: {
Users: { datasetCode: "xxx", tableName: "users" },
Orders: { datasetCode: "yyy", tableName: "orders" },
},
};

ClientConfig

interface ClientConfig {
/** Application code */
appCode?: string;
/** Custom server URL */
serverUrl?: string;
/** Runtime environment, default 'online' */
env?: Environment;

// === Authentication Configuration ===
/** User Token (Bearer authentication) */
token?: string;
/** Timestamp paired with token (required for OpenAPI mode) */
timestamp?: number;
/** API access key (signature authentication) */
accessKey?: string;
/** API secret key (signature authentication) */
secretKey?: string;
/** Whether authentication is required, default true */
requiresAuth?: boolean;

// === Model Configuration ===
/** Direct model configuration */
models?: ModelConfig[] | Record<string, ModelConfig>;
/** Reference to registered configuration name */
apiConfigName?: string;

// === Other Options ===
options?: {
/** Request timeout (milliseconds) */
timeout?: number;
/** Retry count */
retryCount?: number;
/** Error handling callback */
onError?: (error: any) => void;
/** Callback when re-login is required */
onRedirectToLogin?: () => void;
/** Enable debug logging (print request details) */
debug?: boolean;
};
}

Query Types

ListParams

// List query parameters
interface ListParams {
/** Current page number, starting from 1 */
currentPage?: number;
/** Number of items per page */
pageSize?: number;
/** Other query parameters */
[key: string]: any;
}

ListResponse

// List response
interface ListResponse<T> {
/** Data list */
tableData: T[];
/** Total count */
total: number;
/** Current page number */
currentPage: number;
/** Number of items per page */
pageSize: number;
}

ConditionOperator

// Condition operators
type ConditionOperator =
| "$eq" // Equal
| "$ne" // Not equal
| "$gte" // Greater than or equal
| "$gteq" // Greater than or equal (alias)
| "$lte" // Less than or equal
| "$lteq" // Less than or equal (alias)
| "$in" // In set
| "$contain" // Contains (fuzzy match)
| "$startWith" // Starts with
| "$endWith"; // Ends with

FieldCondition and WhereCondition

// Field condition
type FieldCondition = {
[K in ConditionOperator]?: any;
};

// Where condition (supports nesting)
type WhereCondition = {
$and?: WhereCondition[];
$or?: WhereCondition[];
[field: string]: FieldCondition | WhereCondition[] | any;
};

// Usage example
const where: WhereCondition = {
$and: [
{ age: { $gte: 18, $lte: 45 } },
{ country: { $in: ["China", "USA"] } },
{ name: { $contain: "Zhang" } },
],
};

FilterParams

// Filter method parameters (recommended)
interface FilterParams {
/** Where condition */
where?: WhereCondition;
/** Fields to return */
select?: string[];
/** Sort rules */
orderBy?: SortList;
/** Current page number */
currentPage?: number;
/** Number of items per page */
pageSize?: number;
}

// Usage example
const params: FilterParams = {
where: {
$and: [
{ status: { $eq: "active" } },
{ age: { $gte: 18 } },
],
},
select: ["id", "name", "email"],
orderBy: [{ createdAt: SortOrder.DESC }],
currentPage: 1,
pageSize: 20,
};

Select Option Types

SelectOption and SelectOptionsParams

// Select option
interface SelectOption {
label: string;
value: string;
}

// Parameters for getting select options
interface SelectOptionsParams {
/** Field name used as value */
code: string;
/** Field name used as label */
label: string;
}

// Usage example
const options = await client.models.users.getSelectOptions({
code: "user_id",
label: "user_name",
});
// Returns: [{ label: "Zhang San", value: "001" }, { label: "Li Si", value: "002" }]

Model Method Types

BaseModelMethods

interface BaseModelMethods {
/** Get list (basic query) */
getList<T = any>(params?: ListParams, sortList?: SortList): Promise<ListResponse<T>>;

/** Advanced filter query (recommended) */
filter<T = any>(params?: FilterParams): Promise<ListResponse<T>>;

/** Get single record */
getOne<T = any>(id: string | number): Promise<T>;

/** Create data */
create<T = any>(data: Record<string, any>): Promise<T>;

/** Update data */
update<T = any>(id: string | number, data: Record<string, any>): Promise<T>;

/** Delete data */
delete(id: string | number): Promise<void>;

/** Get select options */
getSelectOptions(params: SelectOptionsParams): Promise<SelectOption[]>;

/** Export Excel */
excelExport<T = string>(params?: ListParams): Promise<T>;
}

Business Data Type Definitions

Define Data Models

// User data type
interface User {
id: string;
name: string;
email: string;
status: "active" | "inactive";
createdAt: string;
updatedAt: string;
}

// Data type for creation (excluding auto-generated fields)
type CreateUserData = Omit<User, "id" | "createdAt" | "updatedAt">;

// Data type for update (all fields optional)
type UpdateUserData = Partial<Omit<User, "id" | "createdAt" | "updatedAt">>;

Type-Safe API Calls

const client = createClient();

// Typed query
const result = await client.models.users.filter<User>({
where: { status: { $eq: "active" } },
pageSize: 20,
});
// result.tableData is of type User[]

// Typed single record query
const user = await client.models.users.getOne<User>("123");
// user is of type User

// Typed creation
const newUser = await client.models.users.create<User>({
name: "Zhang San",
email: "zhangsan@example.com",
status: "active",
});

Encapsulate Type-Safe APIs

Generic Model Operation Class

class TypedModel<T, CreateT = Partial<T>, UpdateT = Partial<T>> {
constructor(
private modelName: string,
private client: LovrabetClient
) {}

async filter(params?: FilterParams): Promise<ListResponse<T>> {
return await this.client.models[this.modelName].filter<T>(params);
}

async getOne(id: string): Promise<T> {
return await this.client.models[this.modelName].getOne<T>(id);
}

async create(data: CreateT): Promise<T> {
return await this.client.models[this.modelName].create<T>(data);
}

async update(id: string, data: UpdateT): Promise<T> {
return await this.client.models[this.modelName].update<T>(id, data);
}

async delete(id: string): Promise<void> {
return await this.client.models[this.modelName].delete(id);
}
}

// Usage
const userModel = new TypedModel<User, CreateUserData, UpdateUserData>(
"users",
client
);

const users = await userModel.filter({ pageSize: 10 });
const user = await userModel.create({
name: "Li Si",
email: "lisi@example.com",
status: "active",
});

React Hook Encapsulation

import { useState, useEffect, useCallback } from "react";

interface UseModelResult<T> {
data: T[] | null;
loading: boolean;
error: string | null;
refetch: (params?: FilterParams) => Promise<void>;
}

function useModel<T>(
modelName: string,
initialParams?: FilterParams
): UseModelResult<T> {
const [data, setData] = useState<T[] | null>(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);

const refetch = useCallback(async (params?: FilterParams) => {
setLoading(true);
setError(null);
try {
const response = await client.models[modelName].filter<T>({
...initialParams,
...params,
});
setData(response.tableData);
} catch (err) {
setError(err instanceof Error ? err.message : "Unknown error");
} finally {
setLoading(false);
}
}, [modelName, initialParams]);

useEffect(() => {
refetch();
}, [refetch]);

return { data, loading, error, refetch };
}

// Usage
const { data: users, loading, error } = useModel<User>("users", {
where: { status: { $eq: "active" } },
});

Common Questions

Q: How to add types for custom fields?

interface UserWithCustomFields extends User {
customField: string;
metadata: Record<string, any>;
}

const users = await client.models.users.filter<UserWithCustomFields>();

Q: How to handle dynamic model names?

type ModelNames = "users" | "orders" | "products";

const getModelData = async <T>(modelName: ModelNames): Promise<ListResponse<T>> => {
return await client.models[modelName].filter<T>();
};

Q: How to define query parameter types?

// Automatically generate query parameters based on data type
type QueryParams<T> = {
[K in keyof T]?: T[K] | FieldCondition;
} & FilterParams;

type UserQueryParams = QueryParams<User>;

const searchUsers = async (params: UserQueryParams) => {
return await client.models.users.filter<User>(params);
};

Next Steps