Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork2.8k
fix(eslint-plugin): [unified-signatures] exemptthis
from optional parameter overload check#11005
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Conversation
Thanks for the PR,@jedwards1211! 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 onhttps://opencollective.com/typescript-eslint. |
netlifybot commentedMar 28, 2025 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
✅ Deploy Preview fortypescript-eslint ready!
To edit notification comments on pull requests, go to yourNetlify site configuration. |
nx-cloudbot commentedMar 28, 2025 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
ea91923
to2532ff3
Comparethis
from optional parameter overload checkthis
from optional parameter overload check in unified-signaturescodecovbot commentedMar 28, 2025 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@## main #11005 +/- ##======================================= Coverage 90.83% 90.83% ======================================= Files 497 497 Lines 50279 50304 +25 Branches 8297 8309 +12 =======================================+ Hits 45672 45696 +24- Misses 4592 4593 +1 Partials 15 15
Flags with carried forward coverage won't be shown.Click here to find out more.
🚀 New features to boost your workflow:
|
this
from optional parameter overload check in unified-signaturesthis
from optional parameter overload check in unified-signaturesthis
from optional parameter overload check in unified-signaturesthis
from optional parameter overload checkThere 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.
💯 Great first PR, thanks!
@@ -310,6 +314,12 @@ export default createRule<Options, MessageIds>({ | |||
const shorter = sig1.length < sig2.length ? sig1 : sig2; | |||
const shorterSig = sig1.length < sig2.length ? a : b; | |||
// If one signature has explicit this type and another doesn't, they can't | |||
// be unified. | |||
if (isThisParam(sig1[0]) !== isThisParam(sig2[0])) { |
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 -
if(isThisParam(sig1[0])!==isThisParam(sig2[0])){ | |
if(isThisParam(sig1[0])||isThisParam(sig2[0])){ |
I was kind of thinking we would also want to exempt cases where they both includethis
, sincethis: Foo | void
isn't equivalent to the overload form (playground). Is that not the case?
jedwards1211Mar 31, 2025 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
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.
Wouldn't that break cases that should be flagged for merge like this?
functionfoo(this:SomeClass)functionfoo(this:SomeClass,x:number)
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.
Hmm but using different logic, we could also exempt cases where some but not all signatures havethis: void
without breaking the above example
jedwards1211Mar 31, 2025 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
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.
@kirkwaiblinger btw doesreturnsVoid
(especially calling it with a function argument) do something tricky in your example that I'm not aware of? It seems to me instead of
overloadedThisVoid.call(returnsVoid(()=>'lol'));
you could just do
overloadedThisVoid.call((()=>{})())
Or more explicitly
overloadedThisVoid.call(1asanyasvoid)
Both of which trigger the same TypeScript error.
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.
Hmm, yeah, I guess it would come down to special-casing aroundvoid
, since, in addition to your example, which I agree with, we'd also want to consider:
functionfoo(this:Foo,x:number)functionfoo(this:Bar,x:number)
can still be
functionfoo(this:Foo|Bar,x:number)
Wonder if special-casing aroundvoid
is even relevant for non-this
parameters too?
functionfoo(x:void);functionfoo(x:number);
Would have to play around to figure that one out.
jedwards1211Mar 31, 2025 • edited by kirkwaiblinger
Loading Uh oh!
There was an error while loading.Please reload this page.
edited by kirkwaiblinger
Uh oh!
There was an error while loading.Please reload this page.
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.
It appears that TS picks thethis
type from the last overload when it comes to.call
, lol.
functionfoo(this:string):void;functionfoo(this:number):void;functionfoo(){}foo.call(1)foo.call('a')// Argument of type 'string' is not assignable to parameter of type 'number'.(2345)functionbar(this:number):void;functionbar(this:string|boolean):void;functionbar(){}bar.call(1)// Argument of type 'number' is not assignable to parameter of type 'string | boolean'.(2345)bar.call('a')bar.call(true)
jedwards1211Mar 31, 2025 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
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.
ah right, the unsoundness of TS function typing rears its head again
Do you know why TS doesn't treat embedded void expressions as an error the wayno-confusing-void-expression
does? Would be curious to know the explicit rationale from the TS team.
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.
It appears that TS picks the
this
type from the last overload when it comes to.call
, lol.
Huh. 👀 . Well - that the.bind()
/.call()
/.apply()
types are going over my head at this point 😆
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.
possibly related -microsoft/TypeScript#14107,microsoft/TypeScript#33815,microsoft/TypeScript#38353... they seem to have more to do with teh parameter types than thethis
type, but anyway. Let's not stress too much about bind/call/apply type behavior, I suppose. 🤷
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.
Do you know why TS doesn't treat embedded void expressions as an error the way
no-confusing-void-expression
does? Would be curious to know the explicit rationale from the TS team.
Not off the top of my head, but I'm sure you'll get (or more likely be pointed to) a thorough answer if you ask in the TS discord.
param: TSESTree.Parameter | undefined, | ||
): param is TSESTree.Identifier { | ||
return param?.type === AST_NODE_TYPES.Identifier && param.name === 'this'; | ||
function isThisParam(param: TSESTree.Parameter | undefined): boolean { |
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.
FYI/PSA - I changed this not to be a type predicate since it's only valid in thetrue
branch, not thefalse
branch (the function returningfalse
does not imply thatparam
isnot aTSESTree.Identifier
).
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.
Oh I didn't think about TS doing a negative refinement when the function returnsfalse
. It would be useful to be able to declare an assertion that only refines in thetrue
case
5453629
intotypescript-eslint:mainUh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
PR Checklist
Overview
In
signaturesDifferByOptionalOrRestParameter
, checks the first parameter of both signatures. If one is athis
parameter but not the other, thenreturn undefined
instead ofkind: 'extra-parameter'
, so that no error is flagged.