跳到主要内容

TypeScript 支持

Lovrabet SDK 提供完整的 TypeScript 支持,包括类型定义、类型推断和编译时错误检测。

前置条件

开始之前,请确保已完成 SDK 配置。推荐使用 CLI 自动生成配置

类型导入

import {
createClient,
registerModels,
// 配置类型
type ClientConfig,
type ModelsConfig,
type ModelConfig,
type Environment,
// 查询类型
type ListParams,
type ListResponse,
type FilterParams,
type WhereCondition,
type FieldCondition,
type ConditionOperator,
// 排序类型
type SortList,
SortOrder,
// 下拉选项类型
type SelectOption,
type SelectOptionsParams,
// 模型类型
type BaseModelMethods,
type LovrabetClient,
} from "@lovrabet/sdk";

环境与基础类型

Environment

// 环境类型
type Environment = "online" | "daily";

SortOrder 枚举

// 排序方向
enum SortOrder {
ASC = "asc", // 升序
DESC = "desc", // 降序
}

// 排序配置(数组格式)
type SortList = Record<string, SortOrder>[];

// 使用示例
const sortList: SortList = [
{ id: SortOrder.DESC },
{ name: SortOrder.ASC },
];

配置类型

ModelConfig

// 单个模型配置
interface ModelConfig {
/** 数据表名称(必填) */
tableName: string;
/** 数据集代码(必填,唯一标识) */
datasetCode: string;
/** 显示名称(可选,用于 UI 展示) */
name?: string;
/** 别名(可选,用于 client.models.alias 访问) */
alias?: string;
/** 数据库名称(可选,用于区分不同数据库中的同名表) */
dbName?: string;
}

ModelsConfig

// 模型配置集合
interface ModelsConfig {
/** 应用代码 */
appCode: string;
/**
* 模型配置(支持两种格式)
* - 数组格式(推荐)
* - 对象格式(向下兼容)
*/
models: ModelConfig[] | Record<string, ModelConfig>;
}

// 数组格式(推荐)
const config: ModelsConfig = {
appCode: "my-app",
models: [
{ datasetCode: "xxx", tableName: "users", alias: "users" },
{ datasetCode: "yyy", tableName: "orders", alias: "orders" },
],
};

// 对象格式(向下兼容,key 作为默认 alias)
const legacyConfig: ModelsConfig = {
appCode: "my-app",
models: {
Users: { datasetCode: "xxx", tableName: "users" },
Orders: { datasetCode: "yyy", tableName: "orders" },
},
};

ClientConfig

interface ClientConfig {
/** 应用代码 */
appCode?: string;
/** 自定义服务器 URL */
serverUrl?: string;
/** 运行环境,默认 'online' */
env?: Environment;

// === 认证配置 ===
/** 用户 Token(Bearer 认证) */
token?: string;
/** 与 token 配对的时间戳(OpenAPI 模式必需) */
timestamp?: number;
/** API 访问密钥(签名认证) */
accessKey?: string;
/** API 密钥(签名认证) */
secretKey?: string;
/** 是否需要认证,默认 true */
requiresAuth?: boolean;

// === 模型配置 ===
/** 直接传入模型配置 */
models?: ModelConfig[] | Record<string, ModelConfig>;
/** 引用已注册的配置名称 */
apiConfigName?: string;

// === 其他选项 ===
options?: {
/** 请求超时时间(毫秒) */
timeout?: number;
/** 重试次数 */
retryCount?: number;
/** 错误处理回调 */
onError?: (error: any) => void;
/** 需要重新登录时的回调 */
onRedirectToLogin?: () => void;
/** 启用调试日志(打印请求详情) */
debug?: boolean;
};
}

查询类型

ListParams

// 列表查询参数
interface ListParams {
/** 当前页码,从 1 开始 */
currentPage?: number;
/** 每页数量 */
pageSize?: number;
/** 其他查询参数 */
[key: string]: any;
}

ListResponse

// 列表响应
interface ListResponse<T> {
/** 数据列表 */
tableData: T[];
/** 总数量 */
total: number;
/** 当前页码 */
currentPage: number;
/** 每页数量 */
pageSize: number;
}

ConditionOperator

// 条件操作符
type ConditionOperator =
| "$eq" // 等于
| "$ne" // 不等于
| "$gte" // 大于等于
| "$gteq" // 大于等于(别名)
| "$lte" // 小于等于
| "$lteq" // 小于等于(别名)
| "$in" // 在集合内
| "$contain" // 包含(模糊匹配)
| "$startWith" // 以...开头
| "$endWith"; // 以...结尾

FieldCondition 与 WhereCondition

// 字段条件
type FieldCondition = {
[K in ConditionOperator]?: any;
};

// Where 条件(支持嵌套)
type WhereCondition = {
$and?: WhereCondition[];
$or?: WhereCondition[];
[field: string]: FieldCondition | WhereCondition[] | any;
};

// 使用示例
const where: WhereCondition = {
$and: [
{ age: { $gte: 18, $lte: 45 } },
{ country: { $in: ["中国", "美国"] } },
{ name: { $contain: "张" } },
],
};

FilterParams

// Filter 方法参数(推荐使用)
interface FilterParams {
/** Where 条件 */
where?: WhereCondition;
/** 选择返回的字段 */
select?: string[];
/** 排序规则 */
orderBy?: SortList;
/** 当前页码 */
currentPage?: number;
/** 每页数量 */
pageSize?: number;
}

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

下拉选项类型

SelectOption 与 SelectOptionsParams

// 下拉选项
interface SelectOption {
label: string;
value: string;
}

// 获取下拉选项的参数
interface SelectOptionsParams {
/** 用作 value 的字段名 */
code: string;
/** 用作 label 的字段名 */
label: string;
}

// 使用示例
const options = await client.models.users.getSelectOptions({
code: "user_id",
label: "user_name",
});
// 返回: [{ label: "张三", value: "001" }, { label: "李四", value: "002" }]

模型方法类型

BaseModelMethods

interface BaseModelMethods {
/** 获取列表(基础查询) */
getList<T = any>(params?: ListParams, sortList?: SortList): Promise<ListResponse<T>>;

/** 高级过滤查询(推荐) */
filter<T = any>(params?: FilterParams): Promise<ListResponse<T>>;

/** 获取单条数据 */
getOne<T = any>(id: string | number): Promise<T>;

/** 创建数据 */
create<T = any>(data: Record<string, any>): Promise<T>;

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

/** 删除数据 */
delete(id: string | number): Promise<void>;

/** 获取下拉选项 */
getSelectOptions(params: SelectOptionsParams): Promise<SelectOption[]>;

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

业务数据类型定义

定义数据模型

// 用户数据类型
interface User {
id: string;
name: string;
email: string;
status: "active" | "inactive";
createdAt: string;
updatedAt: string;
}

// 创建时的数据类型(排除自动生成字段)
type CreateUserData = Omit<User, "id" | "createdAt" | "updatedAt">;

// 更新时的数据类型(所有字段可选)
type UpdateUserData = Partial<Omit<User, "id" | "createdAt" | "updatedAt">>;

类型安全的 API 调用

const client = createClient();

// 带类型的查询
const result = await client.models.users.filter<User>({
where: { status: { $eq: "active" } },
pageSize: 20,
});
// result.tableData 类型为 User[]

// 带类型的单条查询
const user = await client.models.users.getOne<User>("123");
// user 类型为 User

// 带类型的创建
const newUser = await client.models.users.create<User>({
name: "张三",
email: "zhangsan@example.com",
status: "active",
});

封装类型安全的 API

通用模型操作类

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);
}
}

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

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

React Hook 封装

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 };
}

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

常见问题

Q: 如何为自定义字段添加类型?

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

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

Q: 如何处理动态模型名称?

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

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

Q: 如何定义查询参数类型?

// 根据数据类型自动生成查询参数
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);
};

下一步