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

          1928 у кіно

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

          Ель Греко