资源类型注册表
资源类型注册表是 svadmin 实现编译时资源名称检查和自动数据类型推断的机制。通过扩展一个 TypeScript 接口,你可以获得防拼写错误的资源名称和完整类型推断。
1. 定义数据类型
Section titled “1. 定义数据类型”export interface Post { id: number; title: string; body: string; status: 'draft' | 'published';}
export interface User { id: number; name: string; email: string;}2. 注册到 ResourceTypeMap
Section titled “2. 注册到 ResourceTypeMap”// resource-types.d.ts(或任何 .ts 文件)import type { Post, User } from './types';
declare module '@svadmin/core' { interface ResourceTypeMap { posts: Post; users: User; }}3. 享受类型安全
Section titled “3. 享受类型安全”// ✅ 编译通过 — 'posts' 是 KnownResources 的键useList({ resource: 'posts' });
// ❌ 编译错误 — 拼写错误被捕获!useList({ resource: 'postz' });
// ✅ 数据自动推断为 Post[]const query = useList({ resource: 'posts' });query.data?.data[0].title; // string ✓svadmin 使用 TypeScript 声明合并对一个空接口进行扩展:
// @svadmin/core 导出:export interface ResourceTypeMap {} // 空接口 — 用户扩展它export type KnownResources = keyof ResourceTypeMap extends never ? string // 无注册 → 接受任意字符串 : Extract<keyof ResourceTypeMap, string>; // 有注册 → 约束类型export type InferData<R extends string> = R extends keyof ResourceTypeMap ? ResourceTypeMap[R] : Record<string, unknown>; // 未知资源 → 基础类型关键设计:当 ResourceTypeMap 为空(无用户注册)时,KnownResources 回退为 string — 未使用注册表的现有代码可以正常工作。
| 类型 | 用途 |
|---|---|
ResourceTypeMap | 扩展以注册资源 → 数据类型的映射 |
KnownResources | 已注册资源名称的联合类型(回退为 string) |
InferData<R> | 推断资源 R 的数据类型 |
BaseRecord | Record<string, unknown> — 所有数据类型的基础 |
配合 Elysia(自动注册)
Section titled “配合 Elysia(自动注册)”@svadmin/elysia 包可以从 Elysia 后端自动推断 ResourceTypeMap:
import type { InferResourceMap } from '@svadmin/elysia';import type { App } from './server';
declare module '@svadmin/core' { interface ResourceTypeMap extends InferResourceMap<App> {}}无需手动类型注册 — 类型直接从服务端路由推导。
- 将注册放在
.d.ts文件中 — 例如项目根目录的resource-types.d.ts - 扩展而非替换 — 始终使用
interface ResourceTypeMap { ... },不要用type ResourceTypeMap = - 每个项目一个注册 — 所有资源放在同一个
declare module块中 - 在自定义 Hook 和组件中使用
InferData:
function usePostList() { return useList<InferData<'posts'>>({ resource: 'posts' });}