-
-
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
feat(eslint-plugin): [no-unsafe-return] check promise any #8693
base: main
Are you sure you want to change the base?
Conversation
Thanks for the PR, @yeonjuan! typescript-eslint is a 100% community driven project, and we are incredibly grateful that you are contributing to that community. The core maintainers work on this in their personal time, so please understand that it may not be possible for them to review your work immediately. Thanks again! 🙏 Please, if you or your company is finding typescript-eslint valuable, help us sustain the project by sponsoring it transparently on https://opencollective.com/typescript-eslint. |
✅ Deploy Preview for typescript-eslint ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A good start! Curious to see what ends up changing in order to support the added test cases.
And a thought - these are realllly tricky. I spent a lot of time myself getting confused over whether the code I was trying out actually should pass or fail 😆.
So, I wonder if we can help the user out by supplying a custom error message for the async cases that don't directly return any
, but whose type evaluates to any
after being Awaited
? Feel free to ignore this if it's a hassle to implement. But, my thought would be something like "Unsafe return of type Promise<any>
that is equivalent to simply returning any
within an async function." I'm curious for your thoughts. And, as said, it's completely ok if you would prefer to ignore this idea!
} | ||
`, | ||
` | ||
async function foo(): any { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question - why do we need this test? As written, this is illegal TS; TS demands you must use Promise<any>
.
My thought is - if we do need to test it, indicate this explicitly with @ts-expect-error
comment. If not, we can remove.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A couple test cases....
In particular a bit of tightening around #8674 (comment) is in order.
And I've thrown in a couple annoying (and, admittedly, somewhat artificial) test cases to tighten up getAwaitedType
, to try to help it match Awaited<T>
, which will collapse Awaited<Promise<Promise<Promise<T>>>>
to T
// (passes)
// should be valid; ok to return any in async function that returns Promise<any>.
async function f(): Promise<any> {
return {} as any;
}
// (passes)
// should be invalid; not ok to return any in async function that returns type narrower than Promise<any>
async function f(): Promise<object> {
return {} as any;
}
// (fails)
// should be invalid; can't return any in sync function returning a Promise (since Promise != any).
function f(): Promise<any> {
return {} as any;
}
// (passes)
// should be invalid; can't return any in sync function returning a Promise (since Promise != any).
function f(): Promise<object> {
return {} as any;
}
// (fails)
// should be valid; ok to return Promise<any> in function returning object.
function f(): object {
return Promise.resolve({} as any);
}
// (passes)
// should be invalid; returning T<any> to function returning T<object>.
function f(): Promise<object> {
return Promise.resolve<any>({});
}
// (passes)
// should be invalid; returning T<any> to function returning T<object>
function f(): Promise<object> {
return Promise.resolve<Promise<Promise<any>>>({} as any);
}
// (passes)
// should be invalid; returning value that awaits to any in async function
// with return type narrower than Promise<any>.
async function f(): Promise<object> {
return Promise.resolve<Promise<Promise<any>>>({} as Promise<any>);
}
// (fails)
// should be invalid; returning value that awaits to any in async function
// with return type narrower than Promise<any>.
async function f(): Promise<object> {
return {} as Promise<Promise<Promise<Promise<any>>>>
}
// (fails)
// should be invalid; returning value that awaits to any in async function
// without return type.
async function f() {
return {} as Promise<Promise<Promise<Promise<any>>>>
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PS
- apologies if I accidentally included a few test cases that you've already written
- i wouldn't be wholly surprised if I got the valid/invalid wrong for a few of these, so feel free to push back if some of them seem incorrect
messageId: 'unsafeReturn', | ||
line: 4, | ||
column: 3, | ||
endColumn: 16, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(nit, optional) If you're gonna include the endColumn
, might as well include the endLine
too for consistency. Here and elsewhere
@kirkwaiblinger I agree, this is great, but how about making the error message a little more concise? |
👍 👍 |
# Conflicts: # packages/eslint-plugin/tests/rules/no-unsafe-return.test.ts
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #8693 +/- ##
==========================================
- Coverage 87.40% 87.24% -0.16%
==========================================
Files 260 251 -9
Lines 12608 12341 -267
Branches 3937 3885 -52
==========================================
- Hits 11020 10767 -253
+ Misses 1313 1304 -9
+ Partials 275 270 -5
Flags with carried forward coverage won't be shown. Click here to find out more.
|
CI is failing, I created a separate PR to fix it. #9037 |
@kirkwaiblinger Thank you for your review. I added test cases and improved messsage. |
PR Checklist
Overview