如何使用可选变量处理 Typescript 函数重载增长
Posted
技术标签:
【中文标题】如何使用可选变量处理 Typescript 函数重载增长【英文标题】:What to do with Typescript Function Overload Growth with Optional Variables 【发布时间】:2021-10-08 10:51:00 【问题描述】:我很难找到一种解决方案来处理打字稿中函数重载的指数级增长,问题是:
假设我有一个 findOne 函数,它获取一个 id,在数据库中查找,然后找到一个 Person:
findOne(id):Promise<Person| undefined>
return query().findById(id);
现在我可以在未找到 Person(id 不存在)的情况下添加一个变量来抛出,并确保在传递变量时 findOne 不会返回 undefined;
findOne(id):Promise<Person|undefined>;
findOne(id,orFail:true):Promise<Person>;
findOne(id,orFail?:true):Promise<Person|undefined>
if (orFail)
return query().findById(id).throwIfNotFound();
return query().findById(id);
现在,如果我有另一个变量来决定是否应该加入人员字段,会发生什么?是的,它将返回类型乘以 2(为每个前一个添加另一种可能是否具有连接字段)
再一次,如果我有更多变量,每个变量都会乘以 2,所以我想我会有 2^optionalVarialesCount
findOne 函数的重载。
有没有更好的方法来做到这一点?我不想为 4 个可选变量重载 16 次,这确实使代码混乱。
【问题讨论】:
如果你有多个选项可以改变重载函数的返回类型,我认为你试图用一个函数做太多事情。我的意思是,是的,有 30 多个重载的 API(通常是因为它们是 javascript API,然后 TypeScript 类型是后来添加的,并且必须适应原始 JavaScript 的狂野西部 :-D )。如果你真的想要有多个对返回类型有影响的选项,我认为没有任何办法可以解决重载的爆炸式增长,因为重载很难编写、阅读、使用和维护。由于选项... ...无论如何都必须进行硬编码以使返回类型不同,我建议尝试将它们组合在一起并让 X 函数与每个 Y 重载,诸如此类。祝你好运,编码愉快! 我自己也得出了同样的结论,但希望错过泛型或其他东西的一些技巧,所以在这里问。顺便谢谢 是的,这是一个很好的问题。 TypeScript 非常丰富,我经常看到一些我认为它无法解决的问题的解决方案。 :-) 【参考方案1】:首先让我们将可选的 props 定义为一个元组:
type Optional = [onFail: true, onPass: false]
您可以在Optional
tuple 中定义任意数量的道具。
现在我们可以重载我们的函数了:
type Person =
tag: 'Person'
type Optional = [onFail: true, onPass: false]
function findOne<
/**
* Infer rest arguments
*/
Rest extends Partial<Optional>,
/**
* 1) if length of Rest arguments extends length of Optional arguments
* it means that all Optional arguments was provided, which in tirn means that
* we should return Promise<Person>
*
* 2) otherwise, if Rest length is less then Optional length, it means
* that no all Optional arguments was passes, which in turn means
* that we should return Promise<Person | undefined>
*/
Return extends
all_passed: Promise<Person>,
not_all_passed: Promise<Person | undefined>,
[
Rest['length'] extends Optional['length'] ? 'all_passed' : 'not_all_passed'
]
>(id: string, ...args: Rest): Return
function findOne(id: string, ...args: Partial<Optional>): Promise<Person | undefined>
return null as any
// Promise<Person | undefined> because not optional arguments are passed
const _ = findOne('id', true)
// Promise<Person> because all optional arguments are passed
const __ = findOne('id', true, false)
Playground
【讨论】:
以上是关于如何使用可选变量处理 Typescript 函数重载增长的主要内容,如果未能解决你的问题,请参考以下文章