microsoft / microsoft/TypeScript

should error on assignment that shadows a prototype method

Open
#60,649 2 comments 3 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Awaiting More Feedback Suggestion
Dominant language
Go
Stars
111k
Forks
14.3k
Avg merge
2d 4h
Merged PRs (30d)
132

Description

🔎 Search Terms

own property, shadow, prototype, method, field, inheritance

🕗 Version & Regression Information
⏯ Playground Link

https://www.typescriptlang.org/play/?ts=5.8.0-dev.20241201#code/MYGwhgzhAEBiD29oG8BQ0PWPAdhALgE4Cuw+8hAFAJQrqYP4AWAlhAHQAOh85+AnpwCmAWSHN4AE2gBeaDVkA+Og1WZseeCCHsQ8AOaUA5BCZhJ8AO4xuvXoKHQAtuKZSj1ANz01AXx-Q-gy2fA5iEpIKaGoYGhBaOnqGRi4R0LjQIfbCHt4M-r5AA

💻 Code
class Foo {
    constructor() {
        this.prototypeMethod = () => {
            console.log('shadows prototype method');
        }
    }
    prototypeMethod() {
        console.log('method on prototype');
    }
}
🙁 Actual behavior

no error

🙂 Expected behavior

error - something like "Type 'Foo' has no instance property named 'prototypeMethod'. If you meant to reassign the method 'prototypeMethod', it must be a function-valued instance property instead of a prototype method.".

I expect an error here because the code is effectively equivalent to

class Foo {
    prototypeMethod = () => {
        console.log('shadows prototype method');
    };
    prototypeMethod() {
        console.log('method on prototype');
    }
}

which is a TS error (see https://github.com/microsoft/TypeScript/issues/13141).

Furthermore, it breaks error reporting in subclasses. The following code correctly reports a TS error due to the extended class not being able to override an instance property with a method:
(playground)

class Foo {
    instanceProperty = () => {
        console.log('function-valued instance property');
    }
}

class Bar extends Foo {
    // TS ERROR: Class 'Foo' defines instance member property 'instanceProperty', but extended class 'Bar' defines it as instance member function.(2425)
    instanceProperty() {
        console.log('overridden with method')
    }
}

const b = new Bar();
b.instanceProperty(); // prints 'function-valued instance property'

However, this does not (playground)

class Foo {
    constructor() {
        this.method = () => {
            console.log('function-valued instance property')
        }
    }
    method() {
        console.log('method');
    }

}

class Bar extends Foo {
    // no error here  :(
    method() {
        console.log('overridden with method')
    }
}

const b = new Bar();
b.method(); // prints 'function-valued instance property'
Additional information about the issue

inspired by https://github.com/typescript-eslint/typescript-eslint/issues/10427

cc @miguel-leon

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the constructor-assignment and subclass examples in the linked TypeScript Playground, then compare them with the equivalent function-valued instance-property case. Trace the compiler's class member and inheritance checks; done means assignments that shadow prototype methods produce the expected diagnostic and subclass overrides are checked consistently.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, typescript
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.