TypeScript: void return type converted to any type?












19















I seem to be not able to comprehend why the following code does not raise error:



var rg: {(): void;} = ;
rg.push(function():string {return "";})


I clearly state that the type should be an array of functions that return void, however I push there a function that returns a string and yet the compiler does not complain. If I change the definition of rg to



var rg: {():number;} = ;


The compiler starts to complain.



Is this a bug or is it how the void return type is supposed to work (i.e. anything goes if void is used, basically making it the same as return type any)?










share|improve this question





























    19















    I seem to be not able to comprehend why the following code does not raise error:



    var rg: {(): void;} = ;
    rg.push(function():string {return "";})


    I clearly state that the type should be an array of functions that return void, however I push there a function that returns a string and yet the compiler does not complain. If I change the definition of rg to



    var rg: {():number;} = ;


    The compiler starts to complain.



    Is this a bug or is it how the void return type is supposed to work (i.e. anything goes if void is used, basically making it the same as return type any)?










    share|improve this question



























      19












      19








      19


      3






      I seem to be not able to comprehend why the following code does not raise error:



      var rg: {(): void;} = ;
      rg.push(function():string {return "";})


      I clearly state that the type should be an array of functions that return void, however I push there a function that returns a string and yet the compiler does not complain. If I change the definition of rg to



      var rg: {():number;} = ;


      The compiler starts to complain.



      Is this a bug or is it how the void return type is supposed to work (i.e. anything goes if void is used, basically making it the same as return type any)?










      share|improve this question
















      I seem to be not able to comprehend why the following code does not raise error:



      var rg: {(): void;} = ;
      rg.push(function():string {return "";})


      I clearly state that the type should be an array of functions that return void, however I push there a function that returns a string and yet the compiler does not complain. If I change the definition of rg to



      var rg: {():number;} = ;


      The compiler starts to complain.



      Is this a bug or is it how the void return type is supposed to work (i.e. anything goes if void is used, basically making it the same as return type any)?







      typescript






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Jul 13 '13 at 19:30









      Drew Noakes

      186k117527616




      186k117527616










      asked Oct 6 '12 at 16:34









      Peter StJPeter StJ

      6972820




      6972820
























          2 Answers
          2






          active

          oldest

          votes


















          21














          This is by design (I'll explain why it's good design shortly). The spec says (in section 3.6.3, abridged for clarity):




          A type S is assignable to a type T, and T is assignable from S, if one of the following is true...





          • S and T are object types and, for each member M in T, one of the following is true:





            • M is a call, construct or index signature and S contains a call, construct or index signature N where




              • the result type of M is Void, or the result type of N is assignable to that of M.








          In this case, we're testing if () => string is assignable to () => void. So either string has to be assignable to void (it isn't), or void has to be void (it is).





          In effect, the rule here is you are allowed to throw away the return value, which is consistent with how e.g. C++ treats void in template resolution.



          function decrementWidgetHeight(w: Widget): number {
          // ... returns the new height of the widget
          }

          function applyToManyWidgets(w: Widget, change: (x: Widget) => void): void {
          // for each widget in the array, apply 'change' to it
          }

          // Later...
          applyToManyWidgets(widgetsToShorten, decrementWidgetHeight); // Should be allowed?


          When we constrain the type of change to be (widget) => void, we're making it so that you can pass decrementWidgetHeight as the second argument even though it has a return value, but still making sure that when we write the body of applyToManyWidgets, we don't accidentally use the return value of change anywhere.



          Note that void is still different than any because this is unallowed:



          function f() { }
          var x = f(); // Disallowed, f() is of type 'void'





          share|improve this answer
























          • +1 - you can test this using: var rg: {(): void;} = ; rg.push(function():string {return "";}) var x = rg[0](); in the TypeScript playground to see the behaviour in action. Change void to string and it will allow the return value to be used.

            – Fenton
            Oct 6 '12 at 22:14











          • Okay it makes sense, but is a little counter intuitive, i.e. allowing to add a function that does not match the type, even if it is void in the definition.

            – Peter StJ
            Oct 7 '12 at 17:55






          • 2





            The spec also says "void is only related to the types Undefined, Null and Any", so I'm not sure the spec is consistent. Definitely unexpected.

            – Roly
            Sep 26 '13 at 20:37











          • as of version 1.4.1.0 as I can see it is allowed to assign void functions calls

            – shabunc
            Jan 25 '15 at 22:23



















          0














          That looks like a bug. You should open a new work item for the issue






          share|improve this answer
























          • Did that, but given the above comment I guess this is intended. Not finding generics much use in TS so far...

            – Roly
            Sep 26 '13 at 20:39











          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%2f12761607%2ftypescript-void-return-type-converted-to-any-type%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









          21














          This is by design (I'll explain why it's good design shortly). The spec says (in section 3.6.3, abridged for clarity):




          A type S is assignable to a type T, and T is assignable from S, if one of the following is true...





          • S and T are object types and, for each member M in T, one of the following is true:





            • M is a call, construct or index signature and S contains a call, construct or index signature N where




              • the result type of M is Void, or the result type of N is assignable to that of M.








          In this case, we're testing if () => string is assignable to () => void. So either string has to be assignable to void (it isn't), or void has to be void (it is).





          In effect, the rule here is you are allowed to throw away the return value, which is consistent with how e.g. C++ treats void in template resolution.



          function decrementWidgetHeight(w: Widget): number {
          // ... returns the new height of the widget
          }

          function applyToManyWidgets(w: Widget, change: (x: Widget) => void): void {
          // for each widget in the array, apply 'change' to it
          }

          // Later...
          applyToManyWidgets(widgetsToShorten, decrementWidgetHeight); // Should be allowed?


          When we constrain the type of change to be (widget) => void, we're making it so that you can pass decrementWidgetHeight as the second argument even though it has a return value, but still making sure that when we write the body of applyToManyWidgets, we don't accidentally use the return value of change anywhere.



          Note that void is still different than any because this is unallowed:



          function f() { }
          var x = f(); // Disallowed, f() is of type 'void'





          share|improve this answer
























          • +1 - you can test this using: var rg: {(): void;} = ; rg.push(function():string {return "";}) var x = rg[0](); in the TypeScript playground to see the behaviour in action. Change void to string and it will allow the return value to be used.

            – Fenton
            Oct 6 '12 at 22:14











          • Okay it makes sense, but is a little counter intuitive, i.e. allowing to add a function that does not match the type, even if it is void in the definition.

            – Peter StJ
            Oct 7 '12 at 17:55






          • 2





            The spec also says "void is only related to the types Undefined, Null and Any", so I'm not sure the spec is consistent. Definitely unexpected.

            – Roly
            Sep 26 '13 at 20:37











          • as of version 1.4.1.0 as I can see it is allowed to assign void functions calls

            – shabunc
            Jan 25 '15 at 22:23
















          21














          This is by design (I'll explain why it's good design shortly). The spec says (in section 3.6.3, abridged for clarity):




          A type S is assignable to a type T, and T is assignable from S, if one of the following is true...





          • S and T are object types and, for each member M in T, one of the following is true:





            • M is a call, construct or index signature and S contains a call, construct or index signature N where




              • the result type of M is Void, or the result type of N is assignable to that of M.








          In this case, we're testing if () => string is assignable to () => void. So either string has to be assignable to void (it isn't), or void has to be void (it is).





          In effect, the rule here is you are allowed to throw away the return value, which is consistent with how e.g. C++ treats void in template resolution.



          function decrementWidgetHeight(w: Widget): number {
          // ... returns the new height of the widget
          }

          function applyToManyWidgets(w: Widget, change: (x: Widget) => void): void {
          // for each widget in the array, apply 'change' to it
          }

          // Later...
          applyToManyWidgets(widgetsToShorten, decrementWidgetHeight); // Should be allowed?


          When we constrain the type of change to be (widget) => void, we're making it so that you can pass decrementWidgetHeight as the second argument even though it has a return value, but still making sure that when we write the body of applyToManyWidgets, we don't accidentally use the return value of change anywhere.



          Note that void is still different than any because this is unallowed:



          function f() { }
          var x = f(); // Disallowed, f() is of type 'void'





          share|improve this answer
























          • +1 - you can test this using: var rg: {(): void;} = ; rg.push(function():string {return "";}) var x = rg[0](); in the TypeScript playground to see the behaviour in action. Change void to string and it will allow the return value to be used.

            – Fenton
            Oct 6 '12 at 22:14











          • Okay it makes sense, but is a little counter intuitive, i.e. allowing to add a function that does not match the type, even if it is void in the definition.

            – Peter StJ
            Oct 7 '12 at 17:55






          • 2





            The spec also says "void is only related to the types Undefined, Null and Any", so I'm not sure the spec is consistent. Definitely unexpected.

            – Roly
            Sep 26 '13 at 20:37











          • as of version 1.4.1.0 as I can see it is allowed to assign void functions calls

            – shabunc
            Jan 25 '15 at 22:23














          21












          21








          21







          This is by design (I'll explain why it's good design shortly). The spec says (in section 3.6.3, abridged for clarity):




          A type S is assignable to a type T, and T is assignable from S, if one of the following is true...





          • S and T are object types and, for each member M in T, one of the following is true:





            • M is a call, construct or index signature and S contains a call, construct or index signature N where




              • the result type of M is Void, or the result type of N is assignable to that of M.








          In this case, we're testing if () => string is assignable to () => void. So either string has to be assignable to void (it isn't), or void has to be void (it is).





          In effect, the rule here is you are allowed to throw away the return value, which is consistent with how e.g. C++ treats void in template resolution.



          function decrementWidgetHeight(w: Widget): number {
          // ... returns the new height of the widget
          }

          function applyToManyWidgets(w: Widget, change: (x: Widget) => void): void {
          // for each widget in the array, apply 'change' to it
          }

          // Later...
          applyToManyWidgets(widgetsToShorten, decrementWidgetHeight); // Should be allowed?


          When we constrain the type of change to be (widget) => void, we're making it so that you can pass decrementWidgetHeight as the second argument even though it has a return value, but still making sure that when we write the body of applyToManyWidgets, we don't accidentally use the return value of change anywhere.



          Note that void is still different than any because this is unallowed:



          function f() { }
          var x = f(); // Disallowed, f() is of type 'void'





          share|improve this answer













          This is by design (I'll explain why it's good design shortly). The spec says (in section 3.6.3, abridged for clarity):




          A type S is assignable to a type T, and T is assignable from S, if one of the following is true...





          • S and T are object types and, for each member M in T, one of the following is true:





            • M is a call, construct or index signature and S contains a call, construct or index signature N where




              • the result type of M is Void, or the result type of N is assignable to that of M.








          In this case, we're testing if () => string is assignable to () => void. So either string has to be assignable to void (it isn't), or void has to be void (it is).





          In effect, the rule here is you are allowed to throw away the return value, which is consistent with how e.g. C++ treats void in template resolution.



          function decrementWidgetHeight(w: Widget): number {
          // ... returns the new height of the widget
          }

          function applyToManyWidgets(w: Widget, change: (x: Widget) => void): void {
          // for each widget in the array, apply 'change' to it
          }

          // Later...
          applyToManyWidgets(widgetsToShorten, decrementWidgetHeight); // Should be allowed?


          When we constrain the type of change to be (widget) => void, we're making it so that you can pass decrementWidgetHeight as the second argument even though it has a return value, but still making sure that when we write the body of applyToManyWidgets, we don't accidentally use the return value of change anywhere.



          Note that void is still different than any because this is unallowed:



          function f() { }
          var x = f(); // Disallowed, f() is of type 'void'






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Oct 6 '12 at 21:06









          Ryan CavanaughRyan Cavanaugh

          97.8k27168177




          97.8k27168177













          • +1 - you can test this using: var rg: {(): void;} = ; rg.push(function():string {return "";}) var x = rg[0](); in the TypeScript playground to see the behaviour in action. Change void to string and it will allow the return value to be used.

            – Fenton
            Oct 6 '12 at 22:14











          • Okay it makes sense, but is a little counter intuitive, i.e. allowing to add a function that does not match the type, even if it is void in the definition.

            – Peter StJ
            Oct 7 '12 at 17:55






          • 2





            The spec also says "void is only related to the types Undefined, Null and Any", so I'm not sure the spec is consistent. Definitely unexpected.

            – Roly
            Sep 26 '13 at 20:37











          • as of version 1.4.1.0 as I can see it is allowed to assign void functions calls

            – shabunc
            Jan 25 '15 at 22:23



















          • +1 - you can test this using: var rg: {(): void;} = ; rg.push(function():string {return "";}) var x = rg[0](); in the TypeScript playground to see the behaviour in action. Change void to string and it will allow the return value to be used.

            – Fenton
            Oct 6 '12 at 22:14











          • Okay it makes sense, but is a little counter intuitive, i.e. allowing to add a function that does not match the type, even if it is void in the definition.

            – Peter StJ
            Oct 7 '12 at 17:55






          • 2





            The spec also says "void is only related to the types Undefined, Null and Any", so I'm not sure the spec is consistent. Definitely unexpected.

            – Roly
            Sep 26 '13 at 20:37











          • as of version 1.4.1.0 as I can see it is allowed to assign void functions calls

            – shabunc
            Jan 25 '15 at 22:23

















          +1 - you can test this using: var rg: {(): void;} = ; rg.push(function():string {return "";}) var x = rg[0](); in the TypeScript playground to see the behaviour in action. Change void to string and it will allow the return value to be used.

          – Fenton
          Oct 6 '12 at 22:14





          +1 - you can test this using: var rg: {(): void;} = ; rg.push(function():string {return "";}) var x = rg[0](); in the TypeScript playground to see the behaviour in action. Change void to string and it will allow the return value to be used.

          – Fenton
          Oct 6 '12 at 22:14













          Okay it makes sense, but is a little counter intuitive, i.e. allowing to add a function that does not match the type, even if it is void in the definition.

          – Peter StJ
          Oct 7 '12 at 17:55





          Okay it makes sense, but is a little counter intuitive, i.e. allowing to add a function that does not match the type, even if it is void in the definition.

          – Peter StJ
          Oct 7 '12 at 17:55




          2




          2





          The spec also says "void is only related to the types Undefined, Null and Any", so I'm not sure the spec is consistent. Definitely unexpected.

          – Roly
          Sep 26 '13 at 20:37





          The spec also says "void is only related to the types Undefined, Null and Any", so I'm not sure the spec is consistent. Definitely unexpected.

          – Roly
          Sep 26 '13 at 20:37













          as of version 1.4.1.0 as I can see it is allowed to assign void functions calls

          – shabunc
          Jan 25 '15 at 22:23





          as of version 1.4.1.0 as I can see it is allowed to assign void functions calls

          – shabunc
          Jan 25 '15 at 22:23













          0














          That looks like a bug. You should open a new work item for the issue






          share|improve this answer
























          • Did that, but given the above comment I guess this is intended. Not finding generics much use in TS so far...

            – Roly
            Sep 26 '13 at 20:39
















          0














          That looks like a bug. You should open a new work item for the issue






          share|improve this answer
























          • Did that, but given the above comment I guess this is intended. Not finding generics much use in TS so far...

            – Roly
            Sep 26 '13 at 20:39














          0












          0








          0







          That looks like a bug. You should open a new work item for the issue






          share|improve this answer













          That looks like a bug. You should open a new work item for the issue







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Oct 6 '12 at 17:38









          Steven IckmanSteven Ickman

          1,81197




          1,81197













          • Did that, but given the above comment I guess this is intended. Not finding generics much use in TS so far...

            – Roly
            Sep 26 '13 at 20:39



















          • Did that, but given the above comment I guess this is intended. Not finding generics much use in TS so far...

            – Roly
            Sep 26 '13 at 20:39

















          Did that, but given the above comment I guess this is intended. Not finding generics much use in TS so far...

          – Roly
          Sep 26 '13 at 20:39





          Did that, but given the above comment I guess this is intended. Not finding generics much use in TS so far...

          – Roly
          Sep 26 '13 at 20:39


















          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%2f12761607%2ftypescript-void-return-type-converted-to-any-type%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

          Liquibase includeAll doesn't find base path

          How to use setInterval in EJS file?

          Petrus Granier-Deferre