如何解决TypeScript可选参数导致的函数重载数量指数增长问题
解决方案
方案1:泛型+配置对象+条件类型(推荐)
把所有开关类参数收拢到同一个options对象中,通过泛型约束options类型,再用条件类型动态推导返回值类型,完全不需要手动写重载,新增参数时只需修改类型定义即可,不会出现组合爆炸问题。
示例代码如下:
// 基础实体类型定义 interface Person { id: string; name: string; } interface Address { id: string; detail: string; } interface Order { id: string; amount: number; } // 查询参数配置类型,新增参数直接在这里追加即可 interface FindOneOptions { orFail?: boolean; withAddress?: boolean; withOrders?: boolean; } // 根据传入的配置动态拼接返回的Person字段 type ResolvedPerson<Options extends FindOneOptions> = Person & (Options['withAddress'] extends true ? { address: Address } : {}) & (Options['withOrders'] extends true ? { orders: Order[] } : {}); // 结合orFail参数判断是否需要排除undefined类型 type FindOneResult<Options extends FindOneOptions> = Options['orFail'] extends true ? ResolvedPerson<Options> : ResolvedPerson<Options> | undefined; // 函数实现,无需写任何重载 function findOne<Options extends FindOneOptions>(id: string, options?: Options): Promise<FindOneResult<Options>> { let queryBuilder = query().findById(id); if (options?.withAddress) queryBuilder = queryBuilder.with('address'); if (options?.withOrders) queryBuilder = queryBuilder.with('orders'); if (options?.orFail) queryBuilder = queryBuilder.throwIfNotFound(); return queryBuilder.exec() as Promise<FindOneResult<Options>>; }
调用时TypeScript会自动推导对应返回类型,完全符合你的预期:
// 自动推导为 Promise<Person | undefined> const res1 = findOne('1'); // 自动推导为 Promise<Person & {address: Address}> const res2 = findOne('1', {orFail: true, withAddress: true}); // 自动推导为 Promise<Person & {address: Address, orders: Order[]} | undefined> const res3 = findOne('1', {withAddress: true, withOrders: true});
方案2:行为拆分
如果参数数量较少,也可以把不同行为拆成独立方法,避免参数组合爆炸,可读性更高:
function findOne(id: string): Promise<Person | undefined> {} function findOneOrFail(id: string): Promise<Person> {} function findOneWithAddress(id: string, orFail?: boolean): Promise<(Person & {address: Address}) | undefined> {}
内容的提问来源于stack exchange,提问作者Ali Molaei
相关产品推荐
相关产品推荐

