SKILL.md
只读
名称
typescript
描述
LobeHub 的 TypeScript 代码规范与类型安全指南。在编辑或修改 TS/TSX/MTS 文件、修复类型报错、决策 interface 与 type 的选型、避免使用 any/object、规范 import type、处理异步流程或使用 ts-expect-error 时使用。
TypeScript 代码风格指南
类型与类型安全
- 当 TypeScript 能够自动推导类型时,避免手写显式类型注解
- 避免隐式
any;必要时必须进行显式类型标注 - 使用更精确的类型:优先使用
Record<PropertyKey, unknown>,避免使用object或any - 定义对象结构(如 React props)时优先使用
interface;联合类型(unions)与交叉类型(intersections)使用type - 优先使用
as const satisfies XyzInterface,而非单纯的as const - 优先使用
@ts-expect-error,其次为@ts-ignore,最后才考虑as any - 避免设计没有实际意义的 null/undefined 参数;必须设计严格的函数契约(contract)
- 优先使用 ES 模块扩展(
declare module '...')而非namespace;严禁引入基于namespace的扩展模式 - 当类型需要扩展能力时,在源码类型处暴露一个轻量且可合并的 interface,让各个功能模块/插件在本地自行扩展,而不是把所有扩展字段全集中拼装在一个注册表中
- 对于包内本地扩展模式(如
PipelineContext.metadata),在读写该字段的处理器(processor)、提供者(provider)或插件(plugin)同级定义对应的 metadata 字段
异步范式
- 优先使用
async/await,避免使用回调函数(callbacks)或.then()链式调用 - IO 操作坚持异步优先(Async-first):新增的 IO 代码(如 fs、child_process 等)在其边界处必须使用异步 API —— 优先选用基于 Promise 的变体,如
import { readFile } from 'fs/promises',默认严禁使用*Sync。函数染色(Function coloring)具有不对称性:我们几乎不需要将 async 迁移为 sync,但如果把 sync 改写为 async(当 IO 变慢、引入并发、或衍生出子进程/网络请求时),会导致整条调用链上层的所有调用方全被强制重写 —— 这是会不断滚雪球的同步优先技术债。异步带来的微小开销(如线程池调度、缓存竞态)不能作为使用同步 API 的借口:竞态问题应当通过缓存 Promise 本身而非缓存最终结果来解决 *Sync仅允许在唯一一种场景下使用:即受限于你无法控制的同步契约内部调用点 —— 比如现有的同步签名调用链(在修 bug 时不要为了重构而重构传毒式的旧同步链,但新建的独立模块绝不能继续延续这种同步链),或者像process.on('exit')这类纯同步回调。模块加载阶段与 CLI 启动初始化并不是例外场景 —— 在这些地方请直接使用顶层await(ESM)- 在确保安全的前提下,使用
Promise.all或Promise.race进行并发操作
模块导入(Imports)
-
本项目配置了
simple-import-sort/imports与consistent-type-imports(fixStyle: 'separate-type-imports') -
独立类型导入:仅导入类型时,一律使用
import type { ... },严禁使用import { type ... }内联语法 -
当一个文件已经包含从某个 npm 包中
import type { ... }的声明,而你需要补充导入该包的值(value)时,必须拆分为两条独立的语句:import type { ChatTopicBotContext } from '@lobechat/types'; import { RequestTrigger } from '@lobechat/types'; -
在每条 import 语句内部,被导入的标识符(specifier)须按字母顺序排序
代码结构
- 优先使用对象解构
- 使用一致且具备自我描述力的命名;避免使用晦涩难懂的缩写
- 用命名清晰的常量替换魔数(magic numbers)和硬编码字符串
- 代码格式化完全交由自动化工具(Linter / Formatter)处理
- 优先选择**命名导出(named exports)**而非
export default—— 这可以保持重构重命名与 IDE 自动导入实时同步,避免使用import Foo from './foo'时随意改名导致的标识符漂移。仅在框架强制要求时才使用export default(如 Next.js 的 page/route/layout、React.lazy 加载目标、或vitest.config.ts等配置文件)。代码库中目前仍存留不少export default,那是历史遗留技术债,绝非推荐范式;在上述框架必需场景之外,新写代码切勿效仿既有的export default - 在编写用于通用校验/解析/规范化的本地工具函数(如 record 判定、字符串提取、空串处理、计时辅助工具、JSON 安全处理工具等)之前,请先在
packages/utils中全局搜索。如果该工具函数已存在或明显属于该包,请直接从@lobechat/utils(或对应的@lobechat/utils/*子路径)导入,切忌在各业务文件中重复实现微型 helper
UI 与主题
- 优先使用
@lobehub/ui和 Ant Design 组件,避免直接使用原生 HTML 标签 - 必须原生支持暗黑模式(Dark mode)与移动端响应式适配
- 使用
antd-style的 Token 系统,严禁硬编码颜色值
性能优化
- 数据库查询时仅选取必要的字段/列
可复用性
- 复用
packages/utils或已安装 npm 包中的现有工具 - 不要手动手写可复用的 record/object-map 类型检查(例如
typeof value === 'object' && value !== null);请直接从@lobechat/utils/object导入isRecord、isPlainRecord、isObjectLike、toRecord、pickString、UnknownRecord等封装好的 helper - 将
Date.now()的结果保存到常量中重复使用,确保单次操作中的时间戳一致
日志规范
- 严禁打印用户隐私敏感信息(如 API Key 等)
- 禁止直接使用
import { log } from 'debug'(会直接输出到 Console) - 在 catch 块中统一使用
console.error,而非 debug 软件包 - 在
.catch()回调中必须记录错误日志 —— 静默的.catch(() => fallback)会吞掉异常导致无法排查问题






