Mixed types checker function to allow calling function with specific type





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







0















I am basically trying to create "checker" function and based on the result of that function, call another function. This another function can only accept single type. The checker function should "filter" unwanted types.



Here is an example:



class A {}

class B {}

const checkB = (entity: A | B): boolean => {
return (entity instanceof B)
}

const execute = (b: B) => {
console.log('executed')
}

const start = (entity: A | B) => {
if (checkB(entity)) {
execute(entity)
}
}

const a = new A()
const b = new B()

start(a)
start(b)


However Flowtype does not like this and returns this error:



execute(entity)
^ Cannot call `execute` with `entity` bound to `b` because `A` [1] is incompatible with `B` [2].
References:
15: const start = (entity: A | B) => {
^ [1]
11: const execute = (b: B) => {
^ [2]


I was wondering if one can somehow convince flow to work this way. Link to Flowtype REPL:
https://flow.org/try/#0PTAEAEDMBsHsHcBQiDG0CGBnToCCoBvAX2TSxwCFCTVYA7TAF1BQAsBTFAayoF5QAFOzqMAlowCeALjygAPqAoBKGQCNYsaO3R1QvAHyFEoUACd2jAK6ndQkeImhRDRjpTtYkRUsQ0U9JlB2AA9OS0Z2PUFVGWU9QwJjFgDNdgA6OABzAQByELCIgBMcnz8A5iZ0U2Z+OzFJGXwFOIMjE1EvATZOHjqHJSU2kyDQlHD2PskfExIyl1B0KLp2eDwBH3951SWVxXXkSuqBdB9DxgFVHyA



EDIT: My environment is set up with Flow v. 0.72.0 but as you can see in the REPL it doesn't work with 0.86.0 either.



Update Nov 26 2018:



There seems to be undocumented %checks annotation that will work that way: https://github.com/facebook/flow/issues/4723#issuecomment-325157852



// @flow

class A {}

class B {}

const checkB = (entity: A | B): boolean %checks => {
return (entity instanceof B)
}

const execute = (b: B) => {
console.log('executed')
}

const start = (entity: A | B) => {
if (checkB(entity)) {
execute(entity)
}
}

const a = new A()
const b = new B()

start(a)
start(b)


This doesn't throw any more errors. However there are some issues with this:




  • does not work if the checkB function is in different module / file

  • does not work with every version of Flow (yes, I'm using older Flow version because of reasons, the code base is pretty large and currently cannot be changed quickly to upgrade to newer Flow version)

  • does not work on class methods (which is actually something I'd need)

  • since it's not documented, I'm a bit skeptic on using it, they might as well remove it later on and I'd be where I started again










share|improve this question































    0















    I am basically trying to create "checker" function and based on the result of that function, call another function. This another function can only accept single type. The checker function should "filter" unwanted types.



    Here is an example:



    class A {}

    class B {}

    const checkB = (entity: A | B): boolean => {
    return (entity instanceof B)
    }

    const execute = (b: B) => {
    console.log('executed')
    }

    const start = (entity: A | B) => {
    if (checkB(entity)) {
    execute(entity)
    }
    }

    const a = new A()
    const b = new B()

    start(a)
    start(b)


    However Flowtype does not like this and returns this error:



    execute(entity)
    ^ Cannot call `execute` with `entity` bound to `b` because `A` [1] is incompatible with `B` [2].
    References:
    15: const start = (entity: A | B) => {
    ^ [1]
    11: const execute = (b: B) => {
    ^ [2]


    I was wondering if one can somehow convince flow to work this way. Link to Flowtype REPL:
    https://flow.org/try/#0PTAEAEDMBsHsHcBQiDG0CGBnToCCoBvAX2TSxwCFCTVYA7TAF1BQAsBTFAayoF5QAFOzqMAlowCeALjygAPqAoBKGQCNYsaO3R1QvAHyFEoUACd2jAK6ndQkeImhRDRjpTtYkRUsQ0U9JlB2AA9OS0Z2PUFVGWU9QwJjFgDNdgA6OABzAQByELCIgBMcnz8A5iZ0U2Z+OzFJGXwFOIMjE1EvATZOHjqHJSU2kyDQlHD2PskfExIyl1B0KLp2eDwBH3951SWVxXXkSuqBdB9DxgFVHyA



    EDIT: My environment is set up with Flow v. 0.72.0 but as you can see in the REPL it doesn't work with 0.86.0 either.



    Update Nov 26 2018:



    There seems to be undocumented %checks annotation that will work that way: https://github.com/facebook/flow/issues/4723#issuecomment-325157852



    // @flow

    class A {}

    class B {}

    const checkB = (entity: A | B): boolean %checks => {
    return (entity instanceof B)
    }

    const execute = (b: B) => {
    console.log('executed')
    }

    const start = (entity: A | B) => {
    if (checkB(entity)) {
    execute(entity)
    }
    }

    const a = new A()
    const b = new B()

    start(a)
    start(b)


    This doesn't throw any more errors. However there are some issues with this:




    • does not work if the checkB function is in different module / file

    • does not work with every version of Flow (yes, I'm using older Flow version because of reasons, the code base is pretty large and currently cannot be changed quickly to upgrade to newer Flow version)

    • does not work on class methods (which is actually something I'd need)

    • since it's not documented, I'm a bit skeptic on using it, they might as well remove it later on and I'd be where I started again










    share|improve this question



























      0












      0








      0








      I am basically trying to create "checker" function and based on the result of that function, call another function. This another function can only accept single type. The checker function should "filter" unwanted types.



      Here is an example:



      class A {}

      class B {}

      const checkB = (entity: A | B): boolean => {
      return (entity instanceof B)
      }

      const execute = (b: B) => {
      console.log('executed')
      }

      const start = (entity: A | B) => {
      if (checkB(entity)) {
      execute(entity)
      }
      }

      const a = new A()
      const b = new B()

      start(a)
      start(b)


      However Flowtype does not like this and returns this error:



      execute(entity)
      ^ Cannot call `execute` with `entity` bound to `b` because `A` [1] is incompatible with `B` [2].
      References:
      15: const start = (entity: A | B) => {
      ^ [1]
      11: const execute = (b: B) => {
      ^ [2]


      I was wondering if one can somehow convince flow to work this way. Link to Flowtype REPL:
      https://flow.org/try/#0PTAEAEDMBsHsHcBQiDG0CGBnToCCoBvAX2TSxwCFCTVYA7TAF1BQAsBTFAayoF5QAFOzqMAlowCeALjygAPqAoBKGQCNYsaO3R1QvAHyFEoUACd2jAK6ndQkeImhRDRjpTtYkRUsQ0U9JlB2AA9OS0Z2PUFVGWU9QwJjFgDNdgA6OABzAQByELCIgBMcnz8A5iZ0U2Z+OzFJGXwFOIMjE1EvATZOHjqHJSU2kyDQlHD2PskfExIyl1B0KLp2eDwBH3951SWVxXXkSuqBdB9DxgFVHyA



      EDIT: My environment is set up with Flow v. 0.72.0 but as you can see in the REPL it doesn't work with 0.86.0 either.



      Update Nov 26 2018:



      There seems to be undocumented %checks annotation that will work that way: https://github.com/facebook/flow/issues/4723#issuecomment-325157852



      // @flow

      class A {}

      class B {}

      const checkB = (entity: A | B): boolean %checks => {
      return (entity instanceof B)
      }

      const execute = (b: B) => {
      console.log('executed')
      }

      const start = (entity: A | B) => {
      if (checkB(entity)) {
      execute(entity)
      }
      }

      const a = new A()
      const b = new B()

      start(a)
      start(b)


      This doesn't throw any more errors. However there are some issues with this:




      • does not work if the checkB function is in different module / file

      • does not work with every version of Flow (yes, I'm using older Flow version because of reasons, the code base is pretty large and currently cannot be changed quickly to upgrade to newer Flow version)

      • does not work on class methods (which is actually something I'd need)

      • since it's not documented, I'm a bit skeptic on using it, they might as well remove it later on and I'd be where I started again










      share|improve this question
















      I am basically trying to create "checker" function and based on the result of that function, call another function. This another function can only accept single type. The checker function should "filter" unwanted types.



      Here is an example:



      class A {}

      class B {}

      const checkB = (entity: A | B): boolean => {
      return (entity instanceof B)
      }

      const execute = (b: B) => {
      console.log('executed')
      }

      const start = (entity: A | B) => {
      if (checkB(entity)) {
      execute(entity)
      }
      }

      const a = new A()
      const b = new B()

      start(a)
      start(b)


      However Flowtype does not like this and returns this error:



      execute(entity)
      ^ Cannot call `execute` with `entity` bound to `b` because `A` [1] is incompatible with `B` [2].
      References:
      15: const start = (entity: A | B) => {
      ^ [1]
      11: const execute = (b: B) => {
      ^ [2]


      I was wondering if one can somehow convince flow to work this way. Link to Flowtype REPL:
      https://flow.org/try/#0PTAEAEDMBsHsHcBQiDG0CGBnToCCoBvAX2TSxwCFCTVYA7TAF1BQAsBTFAayoF5QAFOzqMAlowCeALjygAPqAoBKGQCNYsaO3R1QvAHyFEoUACd2jAK6ndQkeImhRDRjpTtYkRUsQ0U9JlB2AA9OS0Z2PUFVGWU9QwJjFgDNdgA6OABzAQByELCIgBMcnz8A5iZ0U2Z+OzFJGXwFOIMjE1EvATZOHjqHJSU2kyDQlHD2PskfExIyl1B0KLp2eDwBH3951SWVxXXkSuqBdB9DxgFVHyA



      EDIT: My environment is set up with Flow v. 0.72.0 but as you can see in the REPL it doesn't work with 0.86.0 either.



      Update Nov 26 2018:



      There seems to be undocumented %checks annotation that will work that way: https://github.com/facebook/flow/issues/4723#issuecomment-325157852



      // @flow

      class A {}

      class B {}

      const checkB = (entity: A | B): boolean %checks => {
      return (entity instanceof B)
      }

      const execute = (b: B) => {
      console.log('executed')
      }

      const start = (entity: A | B) => {
      if (checkB(entity)) {
      execute(entity)
      }
      }

      const a = new A()
      const b = new B()

      start(a)
      start(b)


      This doesn't throw any more errors. However there are some issues with this:




      • does not work if the checkB function is in different module / file

      • does not work with every version of Flow (yes, I'm using older Flow version because of reasons, the code base is pretty large and currently cannot be changed quickly to upgrade to newer Flow version)

      • does not work on class methods (which is actually something I'd need)

      • since it's not documented, I'm a bit skeptic on using it, they might as well remove it later on and I'd be where I started again







      javascript flowtype






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 26 '18 at 14:39







      user3056783

















      asked Nov 23 '18 at 13:29









      user3056783user3056783

      5111724




      5111724
























          1 Answer
          1






          active

          oldest

          votes


















          0














          Looks like it's this opened issue (consider add your case too :)).



          However, it works well if you delete method checkB and do refinements exactly in start:



          const start = (entity: A | B) => {
          if (entity instanceof B) {
          execute(entity)
          }
          }


          If you have more complex type refinements and need it to be extracted into separate method, you can change checkB into getB, as null refinements seems to works well:



          const getB = (entity: A | B): ?B => {
          return (entity instanceof B) ? entity : null;
          }

          const execute = (b: B) => {
          console.log('executed')
          }

          const start = (entity: A | B) => {
          const b = getB(entity);
          if (b) {
          execute(b)
          }
          }





          share|improve this answer
























          • I hear you, however the example I posted above is greatly simplified application code that I have to maintain and unfortunately this does not solve the problem in the way I want / need.

            – user3056783
            Nov 26 '18 at 14:35












          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%2f53447620%2fmixed-types-checker-function-to-allow-calling-function-with-specific-type%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          0














          Looks like it's this opened issue (consider add your case too :)).



          However, it works well if you delete method checkB and do refinements exactly in start:



          const start = (entity: A | B) => {
          if (entity instanceof B) {
          execute(entity)
          }
          }


          If you have more complex type refinements and need it to be extracted into separate method, you can change checkB into getB, as null refinements seems to works well:



          const getB = (entity: A | B): ?B => {
          return (entity instanceof B) ? entity : null;
          }

          const execute = (b: B) => {
          console.log('executed')
          }

          const start = (entity: A | B) => {
          const b = getB(entity);
          if (b) {
          execute(b)
          }
          }





          share|improve this answer
























          • I hear you, however the example I posted above is greatly simplified application code that I have to maintain and unfortunately this does not solve the problem in the way I want / need.

            – user3056783
            Nov 26 '18 at 14:35
















          0














          Looks like it's this opened issue (consider add your case too :)).



          However, it works well if you delete method checkB and do refinements exactly in start:



          const start = (entity: A | B) => {
          if (entity instanceof B) {
          execute(entity)
          }
          }


          If you have more complex type refinements and need it to be extracted into separate method, you can change checkB into getB, as null refinements seems to works well:



          const getB = (entity: A | B): ?B => {
          return (entity instanceof B) ? entity : null;
          }

          const execute = (b: B) => {
          console.log('executed')
          }

          const start = (entity: A | B) => {
          const b = getB(entity);
          if (b) {
          execute(b)
          }
          }





          share|improve this answer
























          • I hear you, however the example I posted above is greatly simplified application code that I have to maintain and unfortunately this does not solve the problem in the way I want / need.

            – user3056783
            Nov 26 '18 at 14:35














          0












          0








          0







          Looks like it's this opened issue (consider add your case too :)).



          However, it works well if you delete method checkB and do refinements exactly in start:



          const start = (entity: A | B) => {
          if (entity instanceof B) {
          execute(entity)
          }
          }


          If you have more complex type refinements and need it to be extracted into separate method, you can change checkB into getB, as null refinements seems to works well:



          const getB = (entity: A | B): ?B => {
          return (entity instanceof B) ? entity : null;
          }

          const execute = (b: B) => {
          console.log('executed')
          }

          const start = (entity: A | B) => {
          const b = getB(entity);
          if (b) {
          execute(b)
          }
          }





          share|improve this answer













          Looks like it's this opened issue (consider add your case too :)).



          However, it works well if you delete method checkB and do refinements exactly in start:



          const start = (entity: A | B) => {
          if (entity instanceof B) {
          execute(entity)
          }
          }


          If you have more complex type refinements and need it to be extracted into separate method, you can change checkB into getB, as null refinements seems to works well:



          const getB = (entity: A | B): ?B => {
          return (entity instanceof B) ? entity : null;
          }

          const execute = (b: B) => {
          console.log('executed')
          }

          const start = (entity: A | B) => {
          const b = getB(entity);
          if (b) {
          execute(b)
          }
          }






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 24 '18 at 11:46









          AlexAlex

          3,593823




          3,593823













          • I hear you, however the example I posted above is greatly simplified application code that I have to maintain and unfortunately this does not solve the problem in the way I want / need.

            – user3056783
            Nov 26 '18 at 14:35



















          • I hear you, however the example I posted above is greatly simplified application code that I have to maintain and unfortunately this does not solve the problem in the way I want / need.

            – user3056783
            Nov 26 '18 at 14:35

















          I hear you, however the example I posted above is greatly simplified application code that I have to maintain and unfortunately this does not solve the problem in the way I want / need.

          – user3056783
          Nov 26 '18 at 14:35





          I hear you, however the example I posted above is greatly simplified application code that I have to maintain and unfortunately this does not solve the problem in the way I want / need.

          – user3056783
          Nov 26 '18 at 14:35




















          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%2f53447620%2fmixed-types-checker-function-to-allow-calling-function-with-specific-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

          If I really need a card on my start hand, how many mulligans make sense? [duplicate]

          Alcedinidae

          Can an atomic nucleus contain both particles and antiparticles? [duplicate]