microsoft / TypeScript

TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
https://www.typescriptlang.org
Apache License 2.0
101.33k stars 12.54k forks source link

Error "TS2335" false positive #60669

Open AFatNiBBa opened 22 hours ago

AFatNiBBa commented 22 hours ago

πŸ”Ž Search Terms

πŸ•— Version & Regression Information

⏯ Playground Link

https://www.typescriptlang.org/play/?target=99&ts=5.8.0-dev.20241203#code/FAYwNghgzlAEByB7ATgWwmAwpGsDewsRsALogMonICWAdgOYAUAlPocR8gKYkCuytWAEZYAalhReABy7IAdGUo0GLANzsiAX1gB6HRwNFAiYSwA5JJnJTsEBEGJaYAJ6wARl1jcAZrK60QXAAmsHSwELCBstQAbkE2OFBywJrAoAmw5DIg1BjY0HAEAJBQJBAk1CCwANrkTqiuiGByABbQAJK0JXYBALqMiK4AVgBcsLy0ANa0iADutKxFhdx8ArADg7AAvNukzdSJUsiIZCROMrAAPhcS0rI1dQ1NrVAdXf5cfevM6oXaeoYAwFA4gmcy3Kw2OxrRwudyeLg+bjvYKhcKRGixYLgfJJFKgBxQRpcORgRBMAgcdajPDaOhvAKILwZLI5LAJAA0wK5AP+XgwUC4GhCnVGtC4M2ZXGyuQSLGF9K4jMl0rZ+U5XP+VF4go4h2OiFGmSlrLyMDkepOZw8dNK7yVRpVpqg6o4muQ2qFFsQAH1pmhRkg0DKcV7Tucbd1FUzA+hVTAXbz+TriCVkKLxQgULGnXLxAAiPPcouA-55oRVdZSkiwADyQyrPTzyW+QA

πŸ’» Code


class NormalClass {
  toString() {
    return 1 + super.toString();
  } //         ↑ 'super' can only be referenced in a derived class.
}

class SpecialClass {
  static [Symbol.hasInstance](obj: unknown) {
    return obj === this.prototype || super[Symbol.hasInstance](obj);
  } //                               ↑ 'super' can only be referenced in a derived class.
}

console.log({
  obj: {} instanceof SpecialClass,                            // false
  ins: new SpecialClass() instanceof SpecialClass,            // true
  proto: SpecialClass.prototype instanceof SpecialClass,      // true
  proto_norm: NormalClass.prototype instanceof NormalClass,   // false
  str: new NormalClass() + ""                                 // "1[object Object]"
});

πŸ™ Actual behavior

The error "TS2335" is shown for the two marked lines of code

πŸ™‚ Expected behavior

The code works as a charm when executed, so I think the error shouldn't come up in those cases, since is probably a false positive

Additional information about the issue

No response

MartinJohns commented 21 hours ago

If this is intentional you can write extends Object. Otherwise the inheritance chain with Object is hidden.

Duplicate of #49224.

AFatNiBBa commented 21 hours ago

I don't think it's fully a duplicate because it's not only a problem with instance members (Object.prototype.toString()), but also static ones (Function.prototype[Symbol.hasInstance]()).

Moreover, extends Object has real runtime effects, for instance it adds the static members of Object to the class.

The prototype of base classes is Function.prototype, if you explicitly extended Object, it would be the prototype instead

console.log((class { }).__proto__ === Function.prototype)     // true
console.log((class extends Object { }).__proto__ === Object)  // true
console.log((class { }).create)                               // undefined
console.log((class extends Object { }).create)                // function create() { [native code] }
RyanCavanaugh commented 14 hours ago

It's still intentional to not allow any super access without an explicit extends clause. You can write class Foo extends Function if that's important in your code.