背景
作为一款 SDK,提供完善的 TypeScript 类型定义(.d.ts)是对用户最基本的尊重。 AutoForm 的配置项非常复杂,且存在很多联动关系。如何用 TS 准确描述这些关系?
今天带大家做一套类型体操。
挑战一:互斥属性
如果配置了 mode: 'auto',则 interval 必填;如果 mode: 'manual',则 interval 不可填。
错误写法:
typescript
interface Config {
mode: 'auto' | 'manual';
interval?: number;
}
正确写法(Discriminated Unions):
typescript
type AutoConfig = {
mode: 'auto';
interval: number;
};
type ManualConfig = {
mode: 'manual';
interval?: never; // 关键:禁止出现
};
type Config = AutoConfig | ManualConfig;
挑战二:事件回调的类型推导
我们希望用户在监听事件时,能自动推导出 event 对象的类型。
typescript
sdk.on('success', (e) => {
console.log(e.data); // e 应该是 SuccessEvent
});
sdk.on('error', (e) => {
console.log(e.message); // e 应该是 ErrorEvent
});
实现:
typescript
type EventMap = {
success: { any };
error: { message: string; code: number };
};
class SDK {
on<K extends keyof EventMap>(
type: K,
handler: (event: EventMap[K]) => void
) {
// ...
}
}
挑战三:深度 Partial
用户配置时,通常只需要覆盖默认配置的一部分。我们需要一个递归的 Partial。
typescript
type DeepPartial<T> = {
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
};
总结
TypeScript 不仅仅是类型检查工具,更是最好的文档。写好类型定义,能让用户在使用 SDK 时获得极致的智能提示体验,减少查阅文档的时间。
👉 官网地址:51bpms.com