关于 typescript
面向开发者的 TypeScript 代码风格指南,涵盖类型安全、异步 I/O、导入导出、代码复用和日志规范。
主要功能
- 01类型安全与类型设计规则
- 02异步优先的 I/O 指南
- 03导入与导出约定
- 04可复用辅助工具指南
- 05日志与错误处理规则
适用场景
- 01编写新的 TypeScript 模块
- 02为 API 数据结构选择类型
- 03添加文件或子进程 I/O
- 04审查导入、导出与日志
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ lobehub/ lobehub --skill typescript安装后在 Claude Code 中输入/typescript确认已加载。
详细介绍
TypeScript 代码风格指南
类型与类型安全
- 当 TypeScript 可以推断类型时,避免显式标注类型
- 避免隐式使用
any;必要时显式指定类型 - 使用准确的类型:优先使用
Record<PropertyKey, unknown>,而非object或any - 对象结构(例如 React props)优先使用
interface;联合类型和交叉类型使用type - 优先使用
as const satisfies XyzInterface,而非单独使用as const - 优先使用
@ts-expect-error,其次是@ts-ignore,最后才考虑as any - 避免无意义的 null/undefined 参数;设计严格的函数契约
- 优先使用 ES 模块扩充(
declare module '...'),而非namespace;不要引入基于namespace的扩展模式 - 当类型需要可扩展性时,在源类型处公开一个精简的、可合并的接口,并让各个功能或插件在本地扩充它,而不是将所有扩展字段集中到一个注册表文件中
- 对于
PipelineContext.metadata这类包内扩展模式,在读取或写入这些字段的处理器、提供方或插件旁定义元数据字段
异步模式
- IO 优先使用异步:新增 IO 代码(fs、child_process 等)必须在边界处使用异步 API——使用基于 Promise 的变体,例如
import { readFile } from 'fs/promises',默认情况下绝不使用*Sync。函数着色具有非对称性:无需将异步迁移为同步;而当 IO 变慢、需要并发或增加子进程/网络调用时,同步迁移为异步会迫使调用链上的每个调用方都进行重写,因此同步优先造成的技术债会不断累积。异步的微小开销(线程池调度、缓存竞态)不是合理理由:通过缓存 Promise 而非结果即可解决竞态 *Sync仅在一种情况下可以接受:调用点被限制在你无法控制的同步契约内——现有的同步签名调用链(不要在修复 bug 时对旧有的同步调用链进行病毒式重构,但新的独立模块不得延伸这类调用链),或process.on('exit')这类仅支持同步操作的回调。模块加载时和 CLI 启动初始化不属于例外情况——此处应使用顶层await(ESM)
导入
- 让 lint 通过
simple-import-sort/imports和consistent-type-imports强制执行规则,并使用独立的import type语句(fixStyle: 'separate-type-imports')。
代码结构
- 优先使用命名导出,而非
export default——这样重构重命名和 IDE 自动导入能保持同步,也能避免使用import Foo from './foo'时出现的default重命名偏差。仅在框架要求时使用export default(Next.js page/route/layout、React.lazy 目标文件,以及vitest.config.ts这类配置文件)。代码库中仍有许多export default用法——这是历史遗留问题,不是可照搬的模式;除上述框架要求的情况外,不要在新代码中仿照现有的export default用法
可复用性
- 添加守卫、解析、规范化、计时或 JSON 安全辅助函数之前,先搜索
packages/utils和已安装的包。优先复用@lobechat/utils或其相关子路径中的内容,而不是在多个功能中重复实现辅助函数。 - 不要手写可复用的记录/对象映射守卫,例如
typeof value === 'object' && value !== null;应从@lobechat/utils/object导入isRecord、isPlainRecord、isObjectLike、toRecord、pickString、UnknownRecord等辅助函数。 - 将
Date.now()赋给常量一次,并重复使用,以保持一致
日志
- 绝不记录用户的私密信息(API 密钥等)
- 不要直接使用
import { log } from 'debug'(会将日志输出到控制台) - 在 catch 块中使用
console.error,而不是 debug 包 - 始终在
.catch()回调中记录错误——静默的.catch(() => fallback)会吞掉失败,导致无法调试
评论
支持 Markdown