快速上手typescript-definition-style-guide:从零为原生ESM的npm包添加.d.ts类型定义完全教程
【免费下载链接】typescript-definition-style-guideStyle guide for adding type definitions to my npm packages项目地址: https://gitcode.com/gh_mirrors/ty/typescript-definition-style-guide
你的npm包缺少 TypeScript 类型定义,用户在编辑器里只能看到一片any和缺失的自动补全?typescript-definition-style-guide是一个轻量、社区维护的风格指南,为原生 ESM 的 npm 包添加.d.ts类型定义文件提供了一份完整、可执行的清单。照着指南走,新手也能写出高质量类型定义,让用户获得精准的类型提示,让你的包瞬间更专业。🎉
为什么每个npm包都值得拥有.d.ts类型定义
- 用户体验:用户安装你的包后,编辑器立刻提供参数补全、悬停说明和错误检查。
- 专业形象:类型定义是现代化 npm 包的"门面",主流高质量项目几乎都随包自带
.d.ts文件。 - 成本远低于想象:一个类型定义文件常常只有十几行,却能给使用者带来巨大的体验提升。
一句话总结:好的 .d.ts = 一份免费的用户手册 + 一次自动的质量检查。
1分钟了解项目:这是一个什么样的指南
typescript-definition-style-guide 是一个纯文档项目,极其轻量:
| 文件 | 作用 |
|---|---|
| readme.md | 完整的风格指南正文(清单 + 命名规范 + 文档 + 测试) |
| license | CC-BY-4.0 开源许可证 |
| .editorconfig | 统一代码风格:tab 缩进、LF 换行、UTF-8 编码 |
| .gitattributes | 换行符自动转换设置 |
完整指南就在readme.md中,没有任何框架和安装步骤,打开照着做即可。指南默认一个前提:你的包是原生 ESM 模块(即 package.json 中声明了"type": "module")。
准备工作:开始添加类型定义前的3个检查项
- 确认包是原生 ESM—— 指南全程基于此前提编写。
- 确认入口文件名—— 如果入口文件叫
index.js,类型文件就命名为index.d.ts并放在包根目录,此时甚至不用在 package.json 里写types字段,TypeScript 会根据文件名自动推断。 - 确认第三方类型依赖—— 需要的类型要直接安装为依赖(例如把
@types/node装为 dev dependency),不要在类型文件顶部写/// <reference types="node"/>三斜线引用。
类型定义清单速查:14条规则一次看全
指南的核心就是一张清单,以下是最关键条目的速查表:
| # | 规则 | 一句话说明 |
|---|---|---|
| 1 | 代码风格 | tab 缩进 + 分号 |
| 2 | 版本基准 | 面向最新TypeScript 版本编写 |
| 3 | 文档 | 所有导出的属性/方法必须写文档 |
| 4 | 测试 | 类型定义必须被测试(见下文 tsd) |
| 5 | Node 类型 | @types/node装为 dev 依赖,禁用三斜线引用 |
| 6 | 第三方类型 | @types/*装为直接依赖,用 import 引入 |
| 7 | 默认导出 | 使用export default function foo(...)语法 |
| 8 | namespace | 不要使用 |
| 9 | 字段名 | package.json 用"types",不用"typings" |
| 10 | 字段位置 | types放在官方字段之后、自定义字段之前(建议紧跟dependencies/devDependencies) |
| 11 | 文件名 | 入口为index.js时,类型文件为根目录的index.d.ts |
| 12 | files 字段 | 把类型定义文件加入 package.json 的files数组 |
| 13 | PR 标题 | 统一为Add TypeScript definition |
| 14 | 社区贡献 | 顺手帮忙评审他人的类型定义 PR |
💡 指南还提醒:写类型前不妨扫一眼 DefinitelyTyped 的"常见错误"总结,能一次性避开绝大多数坑。
命名与写法:7条约定让类型定义质量立刻提升
这部分是指南的"灵魂",记住这几点就掌握了九成规范:
- 类型不加命名空间前缀:参数类型就叫
Options,不叫FooOptions(除非存在多个同名Options)。 - 数组用简写:
number[]而非Array<number>;只读数组写readonly number[],而非ReadonlyArray<number>。 unknown优于any:只要可能,就别偷懒用any。- 不写缩写:命名用
options而不是opts;接口名不以I开头。 - 多个泛型参数要有可读名称:
Mapper<Element, NewElement>而不是Mapper<T, U>。 - 花括号内不留空格:命名导入、解构、对象字面量都写
{foo}而非{ foo }。 - 拒绝宽松类型:不要用
object、Function,写具体签名如Record<string, number>或(input: string) => boolean。
一个容易忽视的细节:接收"字符串键值对象"时用Record<string, any>,返回这类对象时用Record<string, unknown>—— 前者能让 TypeScript 在赋值时给你最大灵活度,后者会强制调用方先确认类型。
尽量使用只读值
如果一个值本就不该被修改,就不要让 TypeScript 允许它被修改:
type Point = { readonly x: number; readonly y: number; readonly children: readonly Point[]; };返回值、配置选项对象这类"不该被改"的数据最适合加readonly,还可以配合Readonly工具类型把整个对象"冻结"。
显式导入类型、给导入起可读别名
不要依赖隐式全局类型(例如Electron.BrowserWindow),直接从来源导入。如果导入名太泛、容易混淆,就起个别名,比如把Writable导入为WritableStream,一眼就能看出它的用途。
TSDoc文档:类型定义的"门面"
指南要求所有导出的定义都写TSDoc格式的文档,文字可以直接从项目的 readme 里借用。一份标准函数文档长这样:
/** Add two numbers together. @param x - The first number to add. @param y - The second number to add. @returns The sum of `x` and `y`. */ export default function add(x: number, y: number, options?: Options): number;细节不少,但全部为了可读性:
- 句子首字母大写、以句号结尾;不要在行首加
*,也不要硬换行; @param后跟破折号,不要重复类型名;描述与参数名重复时直接省略(options参数甚至无需描述);- 默认值用
@default标签说明;默认值是复杂描述时,写成Default: …的形式; - 用
@returns,不是@return;返回值是void或Promise<void>时直接省略; @example上方留一行空行,示例代码用三个反引号包裹;示例必须是完整可运行、且包含 import 语句的代码。
⚠️ 注意:环境声明不能有默认参数,所以带默认值的函数参数,要把默认值写进参数文档里。
用tsd测试类型定义:质量的最后一道防线
指南要求类型定义文件必须被测试,推荐工具是tsd—— 它在编译期"测试"类型:类型写错,测试直接失败。
标准流程:
- 新建一个名为
index.test-d.ts的测试文件; - 用
expectType断言返回值类型符合预期; - 合理时补充
expectError()负向测试,验证"错误的用法确实会报错"。
import {expectType} from 'tsd'; import delay from './index.js'; expectType<Promise<void>>(delay(200));两个值得记住的经验:
- 测试返回 Promise 的函数时不要写
await:直接断言Promise<…>的类型。否则await也会"放过"普通值,测试就形同虚设。 - 需要传入字面量或只读常量时,记得用const 断言(
as const)。
快速上手:5步给你的包加上类型定义
- 打开 readme.md,把清单完整读一遍;
- 在包根目录创建
index.d.ts(或与入口对应的文件),按上文命名规范写类型; - 为每个导出的 API 补上 TSDoc 文档;
- 接入
tsd,在index.test-d.ts中补上类型断言与负向测试; - 把类型定义文件加入 package.json 的
files字段,按需补types字段(命名为index.d.ts时可省略),最后逐条核对清单。
完成后,用户编辑器里会亮起你包的自动补全提示,价值立竿见影。✨
常见问题(FAQ)
问:我的包是 CommonJS,能用这份指南吗?指南以原生 ESM 包为前提,建议以 ESM 包直接使用;CJS 包可以借鉴其风格规范,但字段配置需按自己的实际情况调整。
问:装个@types/node再用三斜线引用行不行?不行。指南明确要求"直接依赖 + import"的方式,禁止三斜线引用,这样类型依赖才是透明、可管理的。
问:它和 DefinitelyTyped 有什么区别?DefinitelyTyped 集中存放第三方包的类型;而这份指南讲的是如何为自己随包发布的类型定义定标准——两者相辅相成,避坑时还可以参考 DefinitelyTyped 的常见错误总结。
【免费下载链接】typescript-definition-style-guideStyle guide for adding type definitions to my npm packages项目地址: https://gitcode.com/gh_mirrors/ty/typescript-definition-style-guide
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考