如何构建可同时支持Promise和非Promise入参的sort函数
实现方案
该需求完全可以实现,核心思路是不将整个函数标记为async,而是在运行时判断入参类型,分别处理同步和异步场景,保证返回值类型和入参对齐。
完整实现代码
// 类型重载 function sort<T>(list: T[], fn: (item: T) => string | number): T[]; function sort<T>(list: Promise<T[]>, fn: (item: T) => string | number): Promise<T[]>; // 函数实现 function sort<T>( list: T[] | Promise<T[]>, fn: (item: T) => string | number ): T[] | Promise<T[]> { // 排序逻辑抽离,避免重复编写 const sortLogic = (arr: T[]): T[] => { // 浅拷贝原数组,避免修改原数组 return [...arr].sort((a, b) => { const keyA = fn(a); const keyB = fn(b); if (typeof keyA === 'number' && typeof keyB === 'number') { return keyA - keyB; } return String(keyA).localeCompare(String(keyB)); }); }; // 判断入参是否为Promise,分别处理 if (list instanceof Promise) { // 异步场景:Promise链返回排序后的数组,返回值自动为Promise类型 return list.then(sortLogic); } // 同步场景:直接返回排序后的数组,无Promise包裹 return sortLogic(list); }
效果验证
- 同步调用:返回值为数组类型,符合预期
const syncList = [5, 2, 8, 1]; const sortedSync = sort(syncList, item => item); // sortedSync 类型为 number[],值为 [1,2,5,8]
- 异步调用:返回值为Promise类型,符合预期
const asyncList = Promise.resolve([5, 2, 8, 1]); const sortedAsync = sort(asyncList, item => item); // sortedAsync 类型为 Promise<number[]>,await后得到 [1,2,5,8]
核心原理说明
- 未使用
async修饰整个函数,所以不会强制所有返回值都被包裹为Promise - 运行时通过
instanceof Promise判断入参类型,分支返回对应类型的结果 - TypeScript的重载机制可以正确根据入参类型推导返回值类型,不会出现类型丢失问题
内容的提问来源于stack exchange,提问作者carlosV2
相关产品推荐
相关产品推荐

