Allow subclass to override with either a function property or a method












1















class Foo {
foo: () => void
}

class Bar extends Foo {
foo() {}
}


Is there any way to tell TypeScript to allow the above example?



Playground




Class 'Foo' defines instance member property 'foo', but extended class 'Bar' defines it as instance member function.











share|improve this question





























    1















    class Foo {
    foo: () => void
    }

    class Bar extends Foo {
    foo() {}
    }


    Is there any way to tell TypeScript to allow the above example?



    Playground




    Class 'Foo' defines instance member property 'foo', but extended class 'Bar' defines it as instance member function.











    share|improve this question



























      1












      1








      1


      0






      class Foo {
      foo: () => void
      }

      class Bar extends Foo {
      foo() {}
      }


      Is there any way to tell TypeScript to allow the above example?



      Playground




      Class 'Foo' defines instance member property 'foo', but extended class 'Bar' defines it as instance member function.











      share|improve this question
















      class Foo {
      foo: () => void
      }

      class Bar extends Foo {
      foo() {}
      }


      Is there any way to tell TypeScript to allow the above example?



      Playground




      Class 'Foo' defines instance member property 'foo', but extended class 'Bar' defines it as instance member function.








      typescript






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Feb 21 at 23:08







      aleclarson

















      asked Jan 1 at 16:32









      aleclarsonaleclarson

      10.3k64066




      10.3k64066
























          2 Answers
          2






          active

          oldest

          votes


















          2














          That's because you can call a parent method, but not a parent instance member.



          The reason for that is proper methods are saved to the prototype chain, whereas member functions are not.



          class Foo {
          foo() {
          return `Successfully called Foo.foo()`;
          }

          bar = () => {
          return `Successfully called Foo.bar()`;
          }
          }

          console.log(
          ('foo' in Foo.prototype), // true (methods are correctly inherited)
          ('bar' in Foo.prototype), // false (instance properties are not inherited)
          );


          If the property is not in the property chain, an attempt to call it by using super will cause a runtime error.



          class Bar extends Foo {
          foo = () => {
          return super.foo(); // Good: `foo` is in the prototype chain
          }

          bar = () => {
          return super.bar(); // Runtime error: `bar` is not in the prototype chain
          }
          }


          This makes it safe to go from a method to class instance property (here: foo), but not the other way around.






          share|improve this answer

































            0














            The other way around is allowed by TypeScript. 👇🏻



            class Foo {
            foo() { }
            }

            class Bar extends Foo {
            foo: () => void
            constructor() {
            super()
            this.foo = () => { }
            }
            }


            You could also prefix the method with an underscore and then bind it in the constructor. 👇🏻



            class Foo {
            foo: () => void
            }

            class Bar extends Foo {
            constructor() {
            super()
            this.foo = this._foo.bind(this)
            }
            _foo() {}
            }


            It would be nice if TypeScript let you do the following:



            class Foo {
            foo: () => void
            }

            class Bar extends Foo {
            constructor() {
            super()
            // TypeScript should see that the method is always bound.
            this.foo = this.foo.bind(this)
            }
            foo() {}
            }





            share|improve this answer























              Your Answer






              StackExchange.ifUsing("editor", function () {
              StackExchange.using("externalEditor", function () {
              StackExchange.using("snippets", function () {
              StackExchange.snippets.init();
              });
              });
              }, "code-snippets");

              StackExchange.ready(function() {
              var channelOptions = {
              tags: "".split(" "),
              id: "1"
              };
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function() {
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled) {
              StackExchange.using("snippets", function() {
              createEditor();
              });
              }
              else {
              createEditor();
              }
              });

              function createEditor() {
              StackExchange.prepareEditor({
              heartbeatType: 'answer',
              autoActivateHeartbeat: false,
              convertImagesToLinks: true,
              noModals: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: 10,
              bindNavPrevention: true,
              postfix: "",
              imageUploader: {
              brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
              contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
              allowUrls: true
              },
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              });


              }
              });














              draft saved

              draft discarded


















              StackExchange.ready(
              function () {
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53997107%2fallow-subclass-to-override-with-either-a-function-property-or-a-method%23new-answer', 'question_page');
              }
              );

              Post as a guest















              Required, but never shown

























              2 Answers
              2






              active

              oldest

              votes








              2 Answers
              2






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes









              2














              That's because you can call a parent method, but not a parent instance member.



              The reason for that is proper methods are saved to the prototype chain, whereas member functions are not.



              class Foo {
              foo() {
              return `Successfully called Foo.foo()`;
              }

              bar = () => {
              return `Successfully called Foo.bar()`;
              }
              }

              console.log(
              ('foo' in Foo.prototype), // true (methods are correctly inherited)
              ('bar' in Foo.prototype), // false (instance properties are not inherited)
              );


              If the property is not in the property chain, an attempt to call it by using super will cause a runtime error.



              class Bar extends Foo {
              foo = () => {
              return super.foo(); // Good: `foo` is in the prototype chain
              }

              bar = () => {
              return super.bar(); // Runtime error: `bar` is not in the prototype chain
              }
              }


              This makes it safe to go from a method to class instance property (here: foo), but not the other way around.






              share|improve this answer






























                2














                That's because you can call a parent method, but not a parent instance member.



                The reason for that is proper methods are saved to the prototype chain, whereas member functions are not.



                class Foo {
                foo() {
                return `Successfully called Foo.foo()`;
                }

                bar = () => {
                return `Successfully called Foo.bar()`;
                }
                }

                console.log(
                ('foo' in Foo.prototype), // true (methods are correctly inherited)
                ('bar' in Foo.prototype), // false (instance properties are not inherited)
                );


                If the property is not in the property chain, an attempt to call it by using super will cause a runtime error.



                class Bar extends Foo {
                foo = () => {
                return super.foo(); // Good: `foo` is in the prototype chain
                }

                bar = () => {
                return super.bar(); // Runtime error: `bar` is not in the prototype chain
                }
                }


                This makes it safe to go from a method to class instance property (here: foo), but not the other way around.






                share|improve this answer




























                  2












                  2








                  2







                  That's because you can call a parent method, but not a parent instance member.



                  The reason for that is proper methods are saved to the prototype chain, whereas member functions are not.



                  class Foo {
                  foo() {
                  return `Successfully called Foo.foo()`;
                  }

                  bar = () => {
                  return `Successfully called Foo.bar()`;
                  }
                  }

                  console.log(
                  ('foo' in Foo.prototype), // true (methods are correctly inherited)
                  ('bar' in Foo.prototype), // false (instance properties are not inherited)
                  );


                  If the property is not in the property chain, an attempt to call it by using super will cause a runtime error.



                  class Bar extends Foo {
                  foo = () => {
                  return super.foo(); // Good: `foo` is in the prototype chain
                  }

                  bar = () => {
                  return super.bar(); // Runtime error: `bar` is not in the prototype chain
                  }
                  }


                  This makes it safe to go from a method to class instance property (here: foo), but not the other way around.






                  share|improve this answer















                  That's because you can call a parent method, but not a parent instance member.



                  The reason for that is proper methods are saved to the prototype chain, whereas member functions are not.



                  class Foo {
                  foo() {
                  return `Successfully called Foo.foo()`;
                  }

                  bar = () => {
                  return `Successfully called Foo.bar()`;
                  }
                  }

                  console.log(
                  ('foo' in Foo.prototype), // true (methods are correctly inherited)
                  ('bar' in Foo.prototype), // false (instance properties are not inherited)
                  );


                  If the property is not in the property chain, an attempt to call it by using super will cause a runtime error.



                  class Bar extends Foo {
                  foo = () => {
                  return super.foo(); // Good: `foo` is in the prototype chain
                  }

                  bar = () => {
                  return super.bar(); // Runtime error: `bar` is not in the prototype chain
                  }
                  }


                  This makes it safe to go from a method to class instance property (here: foo), but not the other way around.







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Jan 1 at 17:39

























                  answered Jan 1 at 17:21









                  Karol MajewskiKarol Majewski

                  4,186215




                  4,186215

























                      0














                      The other way around is allowed by TypeScript. 👇🏻



                      class Foo {
                      foo() { }
                      }

                      class Bar extends Foo {
                      foo: () => void
                      constructor() {
                      super()
                      this.foo = () => { }
                      }
                      }


                      You could also prefix the method with an underscore and then bind it in the constructor. 👇🏻



                      class Foo {
                      foo: () => void
                      }

                      class Bar extends Foo {
                      constructor() {
                      super()
                      this.foo = this._foo.bind(this)
                      }
                      _foo() {}
                      }


                      It would be nice if TypeScript let you do the following:



                      class Foo {
                      foo: () => void
                      }

                      class Bar extends Foo {
                      constructor() {
                      super()
                      // TypeScript should see that the method is always bound.
                      this.foo = this.foo.bind(this)
                      }
                      foo() {}
                      }





                      share|improve this answer




























                        0














                        The other way around is allowed by TypeScript. 👇🏻



                        class Foo {
                        foo() { }
                        }

                        class Bar extends Foo {
                        foo: () => void
                        constructor() {
                        super()
                        this.foo = () => { }
                        }
                        }


                        You could also prefix the method with an underscore and then bind it in the constructor. 👇🏻



                        class Foo {
                        foo: () => void
                        }

                        class Bar extends Foo {
                        constructor() {
                        super()
                        this.foo = this._foo.bind(this)
                        }
                        _foo() {}
                        }


                        It would be nice if TypeScript let you do the following:



                        class Foo {
                        foo: () => void
                        }

                        class Bar extends Foo {
                        constructor() {
                        super()
                        // TypeScript should see that the method is always bound.
                        this.foo = this.foo.bind(this)
                        }
                        foo() {}
                        }





                        share|improve this answer


























                          0












                          0








                          0







                          The other way around is allowed by TypeScript. 👇🏻



                          class Foo {
                          foo() { }
                          }

                          class Bar extends Foo {
                          foo: () => void
                          constructor() {
                          super()
                          this.foo = () => { }
                          }
                          }


                          You could also prefix the method with an underscore and then bind it in the constructor. 👇🏻



                          class Foo {
                          foo: () => void
                          }

                          class Bar extends Foo {
                          constructor() {
                          super()
                          this.foo = this._foo.bind(this)
                          }
                          _foo() {}
                          }


                          It would be nice if TypeScript let you do the following:



                          class Foo {
                          foo: () => void
                          }

                          class Bar extends Foo {
                          constructor() {
                          super()
                          // TypeScript should see that the method is always bound.
                          this.foo = this.foo.bind(this)
                          }
                          foo() {}
                          }





                          share|improve this answer













                          The other way around is allowed by TypeScript. 👇🏻



                          class Foo {
                          foo() { }
                          }

                          class Bar extends Foo {
                          foo: () => void
                          constructor() {
                          super()
                          this.foo = () => { }
                          }
                          }


                          You could also prefix the method with an underscore and then bind it in the constructor. 👇🏻



                          class Foo {
                          foo: () => void
                          }

                          class Bar extends Foo {
                          constructor() {
                          super()
                          this.foo = this._foo.bind(this)
                          }
                          _foo() {}
                          }


                          It would be nice if TypeScript let you do the following:



                          class Foo {
                          foo: () => void
                          }

                          class Bar extends Foo {
                          constructor() {
                          super()
                          // TypeScript should see that the method is always bound.
                          this.foo = this.foo.bind(this)
                          }
                          foo() {}
                          }






                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered Jan 1 at 16:37









                          aleclarsonaleclarson

                          10.3k64066




                          10.3k64066






























                              draft saved

                              draft discarded




















































                              Thanks for contributing an answer to Stack Overflow!


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid



                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.


                              To learn more, see our tips on writing great answers.




                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function () {
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53997107%2fallow-subclass-to-override-with-either-a-function-property-or-a-method%23new-answer', 'question_page');
                              }
                              );

                              Post as a guest















                              Required, but never shown





















































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown

































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown







                              Popular posts from this blog

                              Can a sorcerer learn a 5th-level spell early by creating spell slots using the Font of Magic feature?

                              Does disintegrating a polymorphed enemy still kill it after the 2018 errata?

                              A Topological Invariant for $pi_3(U(n))$