Skip to content

Extending a class method with prototype assignment confuses the compiler about membership type #22895

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

Closed
mohsen1 opened this issue Mar 27, 2018 · 10 comments
Assignees
Labels
Bug A bug in TypeScript Fixed A PR has been merged for this issue

Comments

@mohsen1
Copy link
Contributor

mohsen1 commented Mar 27, 2018

This is an issue I encountered when working on webpack/webpack#6862

Bug Repository

See the bug repo for complete code
https://github.com/mohsen1/ts-bug-instance-member

Run npm test to run the test

Expected behavior:
No Error
Actual behavior:

index.js:7:19 - error TS2424: Class 'Ex' defines instance member function 'foo', but extended class 'MyClass' defines it as instance member property.

7 MyClass.prototype.foo = function() {
                    ~~~

@sandersn
Copy link
Member

Fix is up at #22935

@mhegazy mhegazy added the Fixed A PR has been merged for this issue label Mar 28, 2018
@mohsen1
Copy link
Contributor Author

mohsen1 commented Apr 1, 2018

@sandersn using the nightly I'm still getting the error

mohsen1/ts-bug-instance-member#1

@sandersn
Copy link
Member

sandersn commented Apr 2, 2018

I see, it looks like it breaks going the other direction, when the base uses prototype assignment. I’ll take anothe look.

@sandersn
Copy link
Member

sandersn commented Apr 2, 2018

Well, actually it turns out that it's the arrow function being used as a method. This is ... weird, but technically correct as long as the author remembers that this isn't an instance of Ex. I'll have a fix up shortly; I see a couple of ways to do it.

@sandersn
Copy link
Member

sandersn commented Apr 2, 2018

Note that --noImplicitThis works with "checkJs": true, but it marks every usage of this outside a class, which makes it hard to use transitionally. So recognising arrow functions as methods is good for understanding existing code, but bad in that it doesn't prevent js authors from possibly buggy new code.

I think the right thing is to prefer understanding existing code, since we hope people with write new code in Typescript. They will, at least, have years of experience lowering their expectations of the correctness of any new Javascript that they write.

@sandersn
Copy link
Member

sandersn commented Apr 2, 2018

OK, the fix is merged. @mohsen1 can you try typescript@next tomorrow?

@mohsen1
Copy link
Contributor Author

mohsen1 commented Apr 2, 2018

Thank you for prompt response @sandersn!

@mohsen1
Copy link
Contributor Author

mohsen1 commented Apr 4, 2018

Still seeing this error with latest TS nightly.

Run yarn tsc in this branch of Webpack to see errors:

https://github.com/mohsen1/webpack/tree/bd1c827c884d943f68bbbf00cd91003875ae0bb2

sample:


lib/NormalModule.js:455:2 - error TS2425: Class 'Module' defines instance member property 'size', but extended class 'NormalModule' defines it as instance member function.

455  size() {
     ~~~~

@sandersn
Copy link
Member

sandersn commented Apr 4, 2018

Yikes! OK, the problem this time is that the initialisers on the base aren't methods at all. They are null, which is definitely not method-like. I think the intention is to document that they are "abstract", but without creating a notImplementedFunction that always throws.

Upon re-reading the override checking code, it seems that the intent of the error is to prevent instance vs property confusion like this:

class Super {
  constructor() {
    this.p = () => 1
  }
}
class Sub extends Super {
  p() { return 2 }
}
console.log(new Sub().p()) // 1 ???!!!?

class Base {
  get x() { return 1 }
}
class Derived extends Base { }
Derived.prototype.x = 2
console.log(new Derived().x) // 1 ??/?? it keeps happening

So "isMethodLike" should really be "isPrototypeProperty" but the compiler is not very good at tracking this distinction. Fortunately, for Javascript special assignments, we can just look at the left-hand-side of the assignment. I'll go make that change.

@sandersn
Copy link
Member

sandersn commented Apr 4, 2018

OK, #23137 improves the isMethodLike check.

@microsoft microsoft locked and limited conversation to collaborators Jul 25, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Bug A bug in TypeScript Fixed A PR has been merged for this issue
Projects
None yet
Development

No branches or pull requests

3 participants