Typescript conditional return type based on string argument The 2019 Stack Overflow Developer Survey Results Are InTypescript: declare return type to be dependent on argument value?How do I make the method return type generic?Passing arguments to C# generic new() of templated typeType definition in object literal in TypeScriptTypeScript Objects as Dictionary types as in C#Are strongly-typed functions as parameters possible in TypeScript?TypeScript Converting a String to a numberHow to convert string to enum in TypeScript?Call new Date with union type “number | string”Typescript: Interfaces vs TypesUsing string literals types in Typescript

On the insanity of kings as an argument against monarchy

Why can Shazam do this?

What do the Banks children have against barley water?

Are USB sockets on wall outlets live all the time, even when the switch is off?

What tool would a Roman-age civilization have to grind silver and other metals into dust?

Springs with some finite mass

What could be the right powersource for 15 seconds lifespan disposable giant chainsaw?

A poker game description that does not feel gimmicky

Is this food a bread or a loaf?

What is the meaning of Triage in Cybersec world?

Monty Hall variation

Output the Arecibo Message

Does duplicating a spell with Wish count as casting that spell?

In microwave frequencies, do you use a circulator when you need a (near) perfect diode?

How to make payment on the internet without leaving a money trail?

The difference between dialogue marks

How can I create a character who can assume the widest possible range of creature sizes?

Inflated grade on resume at previous job, might former employer tell new employer?

What does "rabbited" mean/imply in this sentence?

Unbreakable Formation vs. Cry of the Carnarium

I looked up a future colleague on LinkedIn before I started a job. I told my colleague about it and he seemed surprised. Should I apologize?

Is flight data recorder erased after every flight?

How to create dashed lines/arrows in Illustrator

Are there any other methods to apply to solving simultaneous equations?



Typescript conditional return type based on string argument



The 2019 Stack Overflow Developer Survey Results Are InTypescript: declare return type to be dependent on argument value?How do I make the method return type generic?Passing arguments to C# generic new() of templated typeType definition in object literal in TypeScriptTypeScript Objects as Dictionary types as in C#Are strongly-typed functions as parameters possible in TypeScript?TypeScript Converting a String to a numberHow to convert string to enum in TypeScript?Call new Date with union type “number | string”Typescript: Interfaces vs TypesUsing string literals types in Typescript



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








1















When using union of string literals as input argument, what would it take to remove the casts and put the type into the function header:



const get = <T extends "barcode" | "mqtt">(s: T) =>
s === "barcode" ?
<T extends "barcode" ? scan: () => string : pan: () => string>scan: () => "we are scanning" :
<T extends "barcode" ? scan: () => string : pan: () => string>pan: () => "we are panning"

get("barcode").scan() // OK
get("mqtt").pan() // OK
get("barcode").pan() // Error


I ran into this trying to answer someone else's question: https://stackoverflow.com/a/55059318/2684980.










share|improve this question




























    1















    When using union of string literals as input argument, what would it take to remove the casts and put the type into the function header:



    const get = <T extends "barcode" | "mqtt">(s: T) =>
    s === "barcode" ?
    <T extends "barcode" ? scan: () => string : pan: () => string>scan: () => "we are scanning" :
    <T extends "barcode" ? scan: () => string : pan: () => string>pan: () => "we are panning"

    get("barcode").scan() // OK
    get("mqtt").pan() // OK
    get("barcode").pan() // Error


    I ran into this trying to answer someone else's question: https://stackoverflow.com/a/55059318/2684980.










    share|improve this question
























      1












      1








      1








      When using union of string literals as input argument, what would it take to remove the casts and put the type into the function header:



      const get = <T extends "barcode" | "mqtt">(s: T) =>
      s === "barcode" ?
      <T extends "barcode" ? scan: () => string : pan: () => string>scan: () => "we are scanning" :
      <T extends "barcode" ? scan: () => string : pan: () => string>pan: () => "we are panning"

      get("barcode").scan() // OK
      get("mqtt").pan() // OK
      get("barcode").pan() // Error


      I ran into this trying to answer someone else's question: https://stackoverflow.com/a/55059318/2684980.










      share|improve this question














      When using union of string literals as input argument, what would it take to remove the casts and put the type into the function header:



      const get = <T extends "barcode" | "mqtt">(s: T) =>
      s === "barcode" ?
      <T extends "barcode" ? scan: () => string : pan: () => string>scan: () => "we are scanning" :
      <T extends "barcode" ? scan: () => string : pan: () => string>pan: () => "we are panning"

      get("barcode").scan() // OK
      get("mqtt").pan() // OK
      get("barcode").pan() // Error


      I ran into this trying to answer someone else's question: https://stackoverflow.com/a/55059318/2684980.







      typescript generics






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Mar 8 at 8:36









      Jørgen TvedtJørgen Tvedt

      4501416




      4501416






















          1 Answer
          1






          active

          oldest

          votes


















          1














          The cleanest solution is such cases (although not any more type safe than the type assertions) is to use overloads instead. You can use conditional types in the public signature, and a simple union in the implementation signature. You will need to switch to a function declaration as function expressions (arrow or regular) don't easily suport overloads:



          function get<T extends "barcode" | "mqtt">(s: T): T extends "barcode" ? scan: () => string : pan: () => string 
          function get(s: "barcode" | "mqtt"): scan: () => string | pan: () => string
          return s === "barcode" ?
          scan: () => "we are scanning" :
          pan: () => "we are panning"


          get("barcode").scan() // OK
          get("mqtt").pan() // OK
          get("barcode").pan() // Error





          share|improve this answer























          • This would be better, although not exactly what I was hoping for. Do you have to specify the return type in the implementation?

            – Jørgen Tvedt
            Mar 8 at 13:33











          • @JørgenTvedt I think you can get away with removing it from the implementation. You will get an error id the conditional branches are not in the returned union

            – Titian Cernicova-Dragomir
            Mar 8 at 14:38











          • Ok, but I still don't understand why my code does not work without the casts, that's why I hesitate to mark this as the answer.

            – Jørgen Tvedt
            Mar 9 at 16:37






          • 1





            @JørgenTvedt because Typescript does not reason about conditional types that contain unresolved type parameters. Except for very limited circumstances, it will just check for an exact type match.

            – Titian Cernicova-Dragomir
            Mar 9 at 17:25






          • 1





            @JørgenTvedt Typescript does not take flow analysis to this level. Flow analysis will impact just the types of the variables inside the guarded block. It will not help the compiler infer any conditional types.

            – Titian Cernicova-Dragomir
            Mar 10 at 11:04











          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%2f55059436%2ftypescript-conditional-return-type-based-on-string-argument%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









          1














          The cleanest solution is such cases (although not any more type safe than the type assertions) is to use overloads instead. You can use conditional types in the public signature, and a simple union in the implementation signature. You will need to switch to a function declaration as function expressions (arrow or regular) don't easily suport overloads:



          function get<T extends "barcode" | "mqtt">(s: T): T extends "barcode" ? scan: () => string : pan: () => string 
          function get(s: "barcode" | "mqtt"): scan: () => string | pan: () => string
          return s === "barcode" ?
          scan: () => "we are scanning" :
          pan: () => "we are panning"


          get("barcode").scan() // OK
          get("mqtt").pan() // OK
          get("barcode").pan() // Error





          share|improve this answer























          • This would be better, although not exactly what I was hoping for. Do you have to specify the return type in the implementation?

            – Jørgen Tvedt
            Mar 8 at 13:33











          • @JørgenTvedt I think you can get away with removing it from the implementation. You will get an error id the conditional branches are not in the returned union

            – Titian Cernicova-Dragomir
            Mar 8 at 14:38











          • Ok, but I still don't understand why my code does not work without the casts, that's why I hesitate to mark this as the answer.

            – Jørgen Tvedt
            Mar 9 at 16:37






          • 1





            @JørgenTvedt because Typescript does not reason about conditional types that contain unresolved type parameters. Except for very limited circumstances, it will just check for an exact type match.

            – Titian Cernicova-Dragomir
            Mar 9 at 17:25






          • 1





            @JørgenTvedt Typescript does not take flow analysis to this level. Flow analysis will impact just the types of the variables inside the guarded block. It will not help the compiler infer any conditional types.

            – Titian Cernicova-Dragomir
            Mar 10 at 11:04















          1














          The cleanest solution is such cases (although not any more type safe than the type assertions) is to use overloads instead. You can use conditional types in the public signature, and a simple union in the implementation signature. You will need to switch to a function declaration as function expressions (arrow or regular) don't easily suport overloads:



          function get<T extends "barcode" | "mqtt">(s: T): T extends "barcode" ? scan: () => string : pan: () => string 
          function get(s: "barcode" | "mqtt"): scan: () => string | pan: () => string
          return s === "barcode" ?
          scan: () => "we are scanning" :
          pan: () => "we are panning"


          get("barcode").scan() // OK
          get("mqtt").pan() // OK
          get("barcode").pan() // Error





          share|improve this answer























          • This would be better, although not exactly what I was hoping for. Do you have to specify the return type in the implementation?

            – Jørgen Tvedt
            Mar 8 at 13:33











          • @JørgenTvedt I think you can get away with removing it from the implementation. You will get an error id the conditional branches are not in the returned union

            – Titian Cernicova-Dragomir
            Mar 8 at 14:38











          • Ok, but I still don't understand why my code does not work without the casts, that's why I hesitate to mark this as the answer.

            – Jørgen Tvedt
            Mar 9 at 16:37






          • 1





            @JørgenTvedt because Typescript does not reason about conditional types that contain unresolved type parameters. Except for very limited circumstances, it will just check for an exact type match.

            – Titian Cernicova-Dragomir
            Mar 9 at 17:25






          • 1





            @JørgenTvedt Typescript does not take flow analysis to this level. Flow analysis will impact just the types of the variables inside the guarded block. It will not help the compiler infer any conditional types.

            – Titian Cernicova-Dragomir
            Mar 10 at 11:04













          1












          1








          1







          The cleanest solution is such cases (although not any more type safe than the type assertions) is to use overloads instead. You can use conditional types in the public signature, and a simple union in the implementation signature. You will need to switch to a function declaration as function expressions (arrow or regular) don't easily suport overloads:



          function get<T extends "barcode" | "mqtt">(s: T): T extends "barcode" ? scan: () => string : pan: () => string 
          function get(s: "barcode" | "mqtt"): scan: () => string | pan: () => string
          return s === "barcode" ?
          scan: () => "we are scanning" :
          pan: () => "we are panning"


          get("barcode").scan() // OK
          get("mqtt").pan() // OK
          get("barcode").pan() // Error





          share|improve this answer













          The cleanest solution is such cases (although not any more type safe than the type assertions) is to use overloads instead. You can use conditional types in the public signature, and a simple union in the implementation signature. You will need to switch to a function declaration as function expressions (arrow or regular) don't easily suport overloads:



          function get<T extends "barcode" | "mqtt">(s: T): T extends "barcode" ? scan: () => string : pan: () => string 
          function get(s: "barcode" | "mqtt"): scan: () => string | pan: () => string
          return s === "barcode" ?
          scan: () => "we are scanning" :
          pan: () => "we are panning"


          get("barcode").scan() // OK
          get("mqtt").pan() // OK
          get("barcode").pan() // Error






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Mar 8 at 9:09









          Titian Cernicova-DragomirTitian Cernicova-Dragomir

          73.3k35370




          73.3k35370












          • This would be better, although not exactly what I was hoping for. Do you have to specify the return type in the implementation?

            – Jørgen Tvedt
            Mar 8 at 13:33











          • @JørgenTvedt I think you can get away with removing it from the implementation. You will get an error id the conditional branches are not in the returned union

            – Titian Cernicova-Dragomir
            Mar 8 at 14:38











          • Ok, but I still don't understand why my code does not work without the casts, that's why I hesitate to mark this as the answer.

            – Jørgen Tvedt
            Mar 9 at 16:37






          • 1





            @JørgenTvedt because Typescript does not reason about conditional types that contain unresolved type parameters. Except for very limited circumstances, it will just check for an exact type match.

            – Titian Cernicova-Dragomir
            Mar 9 at 17:25






          • 1





            @JørgenTvedt Typescript does not take flow analysis to this level. Flow analysis will impact just the types of the variables inside the guarded block. It will not help the compiler infer any conditional types.

            – Titian Cernicova-Dragomir
            Mar 10 at 11:04

















          • This would be better, although not exactly what I was hoping for. Do you have to specify the return type in the implementation?

            – Jørgen Tvedt
            Mar 8 at 13:33











          • @JørgenTvedt I think you can get away with removing it from the implementation. You will get an error id the conditional branches are not in the returned union

            – Titian Cernicova-Dragomir
            Mar 8 at 14:38











          • Ok, but I still don't understand why my code does not work without the casts, that's why I hesitate to mark this as the answer.

            – Jørgen Tvedt
            Mar 9 at 16:37






          • 1





            @JørgenTvedt because Typescript does not reason about conditional types that contain unresolved type parameters. Except for very limited circumstances, it will just check for an exact type match.

            – Titian Cernicova-Dragomir
            Mar 9 at 17:25






          • 1





            @JørgenTvedt Typescript does not take flow analysis to this level. Flow analysis will impact just the types of the variables inside the guarded block. It will not help the compiler infer any conditional types.

            – Titian Cernicova-Dragomir
            Mar 10 at 11:04
















          This would be better, although not exactly what I was hoping for. Do you have to specify the return type in the implementation?

          – Jørgen Tvedt
          Mar 8 at 13:33





          This would be better, although not exactly what I was hoping for. Do you have to specify the return type in the implementation?

          – Jørgen Tvedt
          Mar 8 at 13:33













          @JørgenTvedt I think you can get away with removing it from the implementation. You will get an error id the conditional branches are not in the returned union

          – Titian Cernicova-Dragomir
          Mar 8 at 14:38





          @JørgenTvedt I think you can get away with removing it from the implementation. You will get an error id the conditional branches are not in the returned union

          – Titian Cernicova-Dragomir
          Mar 8 at 14:38













          Ok, but I still don't understand why my code does not work without the casts, that's why I hesitate to mark this as the answer.

          – Jørgen Tvedt
          Mar 9 at 16:37





          Ok, but I still don't understand why my code does not work without the casts, that's why I hesitate to mark this as the answer.

          – Jørgen Tvedt
          Mar 9 at 16:37




          1




          1





          @JørgenTvedt because Typescript does not reason about conditional types that contain unresolved type parameters. Except for very limited circumstances, it will just check for an exact type match.

          – Titian Cernicova-Dragomir
          Mar 9 at 17:25





          @JørgenTvedt because Typescript does not reason about conditional types that contain unresolved type parameters. Except for very limited circumstances, it will just check for an exact type match.

          – Titian Cernicova-Dragomir
          Mar 9 at 17:25




          1




          1





          @JørgenTvedt Typescript does not take flow analysis to this level. Flow analysis will impact just the types of the variables inside the guarded block. It will not help the compiler infer any conditional types.

          – Titian Cernicova-Dragomir
          Mar 10 at 11:04





          @JørgenTvedt Typescript does not take flow analysis to this level. Flow analysis will impact just the types of the variables inside the guarded block. It will not help the compiler infer any conditional types.

          – Titian Cernicova-Dragomir
          Mar 10 at 11:04



















          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%2f55059436%2ftypescript-conditional-return-type-based-on-string-argument%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

          AWS Lex not identifying response if by a variable The 2019 Stack Overflow Developer Survey Results Are In Announcing the arrival of Valued Associate #679: Cesar Manara Planned maintenance scheduled April 17/18, 2019 at 00:00UTC (8:00pm US/Eastern) The Ask Question Wizard is Live! Data science time! April 2019 and salary with experienceEnforcing custom enumeration in AWS LEX for slot valuesHow to give response based on user response in Amazon Lex?Intercepting AWS Lambda Response to a AWS Lex QueryLex chat bot error: Reached second execution of fulfillment lambda on the same utteranceamazon lex showing invalid responseLambda response send back to Lex slot?Response card in Amazon lexAmazon Lex - Lambda response return HTML to botHow can I solve 424 (Failed Dependency) (python) obtained from Amazon lex?

          Алба-Юлія

          Захаров Федір Захарович