-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enhancement: [require-await] add option to ignore overrides
methods
#7536
Comments
Duplicate (or at least highly related to) #7450 |
I'll be honest when I say that the other issue and this one should probably be closed cos it's not overly correct to use There's no specific reason that an implementation of an interface or an override must also be I'm of two minds here as to whether or not this should be done. The entire point of the rule is to enforce the code explicitly does not leverage this implicit promise-wrapping behaviour and I don't really think that satisfying a contract should be valid for the rule? Maybe behind an option but IDK. There's a lot of type work that would need to be done to resolve this information so it wouldn't be a cheap option. |
overrides
methods
@bradzacher What you mentioned - "There's no specific reason that an implementation of an interface or an override must also be async - it's just a "lazy" way to satisfy the contract of returning a promise." is absolutely true, though I'd say that in fact So if the ergonomic benefit of |
I would disagree because it's not just syntactic sugar for So whilst, yes, you could write code without it - it vastly improves things. OTOH adding For example one could argue that the type F = () => Promise<number>;
const fn: F = async () => 1; Just like the overrides case, this case leverages So if if the rule allows one - should it not support the other as well? I don't think so. I think that the point of the rule is that you should avoid The issue with ignoring this sort of case is that it's hard for a future reader to understand whether or not you really meant to use the keyword lazily or not. |
Let me share our motivating example instead: We're using rpc framework that generates
The rpc call signature is async because commonly the server has to make database or other network calls inside, and the interface should allow them, although not necessarily always used, depending on RPCs (e.g., returning from a memory cache or constants, simple synchronous computations, etc,..). This is the server side codebase so it's very clear for our engineers that the top level RPCs are async and that's the way it is. There isn't much added clarity from converting non-awaiting rpc calls to sync-promise returning style in this context. We have three options for these cases (non-awaiting rpc calls):
We don't feel like 3 is worth the complexity, and we don't always have the ability to make upstream library changes. While 2 is doable but it's a bit more cumbersome than 1, without any benefit in this context, so we prefer 1. There is also a different example but the theme is the same: The interface is async to allow async calls inside, but it's a matter of choice(of an implementation) rather than an expectation, and not using I'm not claiming all the cases are like these, hence not suggesting as a default rule (though in our experience, we find that when someone makes a choice to make an async signature as a part of interface, that's usually a careful choice and rarely incorrect), but I think having an option is reasonable. |
I think that's the right solution. The server-generated interfaces are forcing you to do something you don't need to do: explicitly return Promises from your functions. But there's nothing inherent to the code patterns that need your functions to be async / return Promises! We've seen this also with async functions in frameworks such as Next.js. One library/framework says that a function must return export const getServerSideProps: GetServerSideProps = () => {
// ~~~~~~~~~~~~~~~~~~
// Type '() => { props: { movies: never[]; }; }' is not assignable to type 'GetServerSideProps<{}>'.
// Type '{ props: { movies: never[]; }; }' is missing the following properties
// from type 'Promise<GetServerSidePropsResult<{}>>':
...
}; As Josh said, this isn't quite a duplicate of #7450, but is highly related. Closing for the same reason. tl;dr: the rule is right and the types are wrong. 😄 |
Before You File a Proposal Please Confirm You Have Done The Following...
My proposal is suitable for this project
Link to the rule's documentation
https://typescript-eslint.io/rules/require-await
Description
"require-await" rule asserts an existence of
await
insideasync
function. However, when a class method is inherited from a parentasync
method, sometimes it's inevitable to keepasync
signature even when the body doesn't have anyawait
. Of course, one workaround is declaring it as a sync function then returningPromise.resolve(...)
but that's less ergonomic.So my proposal is adding an option called, let's say "AllowInOverriddenFunctions", that allows
async
functions withoutawait
for overridden functions. Please take a look at the example below.Pass
Additional Info
No response
The text was updated successfully, but these errors were encountered: