JavaScript工具库中如何优雅地为singlePromise函数定义类型声明?

JavaScript工具库中如何优雅地为singlePromise函数定义类型声明?
最新回答
一见钟情我相信

2022-01-05 16:26:31

在JavaScript工具库中,可以通过定义SingleOptions接口、SingleFunc泛型接口,并使用条件类型与泛型参数,为singlePromise函数编写类型声明文件(.d.ts),实现优雅的类型定义。

以下是具体实现步骤与代码解析:

1. 定义配置接口SingleOptions

用于管理singlePromise的缓存行为,例如设置缓存时间(cache字段)。

interface SingleOptions { cache?: number; // 可选,缓存时间(毫秒),未设置时可能默认永久缓存}2. 定义泛型接口SingleFunc

该接口描述singlePromise返回的函数对象类型,需满足以下要求:

  • 支持泛型参数P(参数类型数组)和T(返回值类型)。
  • 根据T是否为Promise类型,动态决定返回值类型:

    若T是Promise<U>,则直接返回T。

    若T是非Promise类型,则包装为Promise<T>。

  • 包含update和clear方法,用于更新配置和清除缓存。
interface SingleFunc<P extends any[] = [], T extends unknown = unknown> { (...args: P): T extends Promise<infer U> ? T : Promise<T>; // 条件类型实现动态返回 update(opt?: SingleOptions): void; // 更新缓存配置 clear(): void; // 清除缓存}3. 声明singlePromise函数类型

使用泛型参数P和T,将输入函数fn的参数和返回值类型传递给SingleFunc,确保类型推断准确。

export function singlePromise<P extends any[] = [], T extends unknown = unknown>( fn: (...args: P) => T, // 输入函数,参数为P,返回T opt?: SingleOptions // 可选配置): SingleFunc<P, T>; // 返回符合SingleFunc类型的对象完整类型声明文件示例// 配置接口:管理缓存行为interface SingleOptions { cache?: number;}// 泛型接口:描述返回的函数对象类型interface SingleFunc<P extends any[] = [], T extends unknown = unknown> { // 动态返回值类型:根据T是否为Promise决定 (...args: P): T extends Promise<infer U> ? T : Promise<T>; update(opt?: SingleOptions): void; // 更新配置 clear(): void; // 清除缓存}// 导出singlePromise函数类型声明export function singlePromise<P extends any[] = [], T extends unknown = unknown>( fn: (...args: P) => T, opt?: SingleOptions): SingleFunc<P, T>;关键点解析
  • 条件类型:T extends Promise<infer U> ? T : Promise<T>确保无论输入函数fn返回同步值还是异步Promise,SingleFunc的返回值类型均正确推断。
  • 泛型参数:P和T分别捕获fn的参数和返回值类型,避免类型丢失。
  • 方法扩展:update和clear方法增强了单例函数的灵活性,允许运行时调整缓存策略。
使用示例// 同步函数示例const getSyncData = singlePromise((id: number) => `Data-${id}`);getSyncData(1).then(console.log); // 返回值类型为Promise<string>// 异步函数示例const getAsyncData = singlePromise(async (id: number) => { return fetch(`/api/${id}`).then(res => res.json());});getAsyncData(1).then(console.log); // 返回值类型为Promise<any>(实际应为Promise<APIResponse>,需进一步约束)// 更新缓存配置getSyncData.update({ cache: 1000 }); // 缓存1秒getSyncData.clear(); // 清除缓存

通过上述定义,TypeScript能对singlePromise进行完整的类型检查,并提供准确的代码提示,显著提升工具库的可靠性和开发体验。