Flowtype extend object type










5














As JavaScript developer I'm new to type checking and I struggle to understand why this simple code is not working:






type Animal = 
id: number,
name: string,
type: 'dog' ;

type Dog =
id: number,
name: string,
type: 'dog',
color: string
;

function printAnimal(animal: Animal): string
return `$animal.type: $animal.name`;


const buddy: Dog =
id: 1,
name: 'Buddy',
type: 'dog',
color: 'black'


printAnimal(buddy);





What I'm trying to achieve here is to have a method that accepts interface. This however gives me error: Cannot call 'printAnimal' with 'buddy' bound to 'animal' because string literal 'dog' [1] is incompatible with string literal 'cat' [2] in property 'type'..



What I tried:




  1. interface Animal // ... - does not work.

  2. Remove typing from buddy - it work's but I'm not satisfied. Sometimes I do want to have more strict type (so I know I'm dealing with dog not cat) but still use general method that accept any animal.

  3. I tried changing type: 'dog' | 'cat' to type: string - does not work. I would expect 'dog' string is subtype of general string type but it's not. On the other hand even if it works it wouldn't be enough - sometimes I know that my app accepts only dogs and cats not any other animals.

Thanks for reading and I hope I can get some help from you guys! Here's live version: Try Flow - live example










share|improve this question

















  • 2




    I've been able to find solution by actually specifing two explicit type definitions: for cat and dog and then create a type out of those two with disjoint union. Here's live version. Still looking for better ways!
    – Ernest Nowacki
    Nov 12 at 11:10










  • after playing around a bit, I found this cyclic weirdness to be working: live. Well kind of, because imo. this animal.color should throw, as Cat doesn't implement a color
    – Thomas
    Nov 14 at 12:08











  • Thanks for your input @Thomas ! It's definitely nice that your solution is not throwing error however I don't like cyclomatic complexity - it looks like Animal now needs Cat type to be defined and Cat type need Animal type to be defined. So for now I'm rolling with type Animal = Cat | Dog.
    – Ernest Nowacki
    Nov 16 at 10:41















5














As JavaScript developer I'm new to type checking and I struggle to understand why this simple code is not working:






type Animal = 
id: number,
name: string,
type: 'dog' ;

type Dog =
id: number,
name: string,
type: 'dog',
color: string
;

function printAnimal(animal: Animal): string
return `$animal.type: $animal.name`;


const buddy: Dog =
id: 1,
name: 'Buddy',
type: 'dog',
color: 'black'


printAnimal(buddy);





What I'm trying to achieve here is to have a method that accepts interface. This however gives me error: Cannot call 'printAnimal' with 'buddy' bound to 'animal' because string literal 'dog' [1] is incompatible with string literal 'cat' [2] in property 'type'..



What I tried:




  1. interface Animal // ... - does not work.

  2. Remove typing from buddy - it work's but I'm not satisfied. Sometimes I do want to have more strict type (so I know I'm dealing with dog not cat) but still use general method that accept any animal.

  3. I tried changing type: 'dog' | 'cat' to type: string - does not work. I would expect 'dog' string is subtype of general string type but it's not. On the other hand even if it works it wouldn't be enough - sometimes I know that my app accepts only dogs and cats not any other animals.

Thanks for reading and I hope I can get some help from you guys! Here's live version: Try Flow - live example










share|improve this question

















  • 2




    I've been able to find solution by actually specifing two explicit type definitions: for cat and dog and then create a type out of those two with disjoint union. Here's live version. Still looking for better ways!
    – Ernest Nowacki
    Nov 12 at 11:10










  • after playing around a bit, I found this cyclic weirdness to be working: live. Well kind of, because imo. this animal.color should throw, as Cat doesn't implement a color
    – Thomas
    Nov 14 at 12:08











  • Thanks for your input @Thomas ! It's definitely nice that your solution is not throwing error however I don't like cyclomatic complexity - it looks like Animal now needs Cat type to be defined and Cat type need Animal type to be defined. So for now I'm rolling with type Animal = Cat | Dog.
    – Ernest Nowacki
    Nov 16 at 10:41













5












5








5


2





As JavaScript developer I'm new to type checking and I struggle to understand why this simple code is not working:






type Animal = 
id: number,
name: string,
type: 'dog' ;

type Dog =
id: number,
name: string,
type: 'dog',
color: string
;

function printAnimal(animal: Animal): string
return `$animal.type: $animal.name`;


const buddy: Dog =
id: 1,
name: 'Buddy',
type: 'dog',
color: 'black'


printAnimal(buddy);





What I'm trying to achieve here is to have a method that accepts interface. This however gives me error: Cannot call 'printAnimal' with 'buddy' bound to 'animal' because string literal 'dog' [1] is incompatible with string literal 'cat' [2] in property 'type'..



What I tried:




  1. interface Animal // ... - does not work.

  2. Remove typing from buddy - it work's but I'm not satisfied. Sometimes I do want to have more strict type (so I know I'm dealing with dog not cat) but still use general method that accept any animal.

  3. I tried changing type: 'dog' | 'cat' to type: string - does not work. I would expect 'dog' string is subtype of general string type but it's not. On the other hand even if it works it wouldn't be enough - sometimes I know that my app accepts only dogs and cats not any other animals.

Thanks for reading and I hope I can get some help from you guys! Here's live version: Try Flow - live example










share|improve this question













As JavaScript developer I'm new to type checking and I struggle to understand why this simple code is not working:






type Animal = 
id: number,
name: string,
type: 'dog' ;

type Dog =
id: number,
name: string,
type: 'dog',
color: string
;

function printAnimal(animal: Animal): string
return `$animal.type: $animal.name`;


const buddy: Dog =
id: 1,
name: 'Buddy',
type: 'dog',
color: 'black'


printAnimal(buddy);





What I'm trying to achieve here is to have a method that accepts interface. This however gives me error: Cannot call 'printAnimal' with 'buddy' bound to 'animal' because string literal 'dog' [1] is incompatible with string literal 'cat' [2] in property 'type'..



What I tried:




  1. interface Animal // ... - does not work.

  2. Remove typing from buddy - it work's but I'm not satisfied. Sometimes I do want to have more strict type (so I know I'm dealing with dog not cat) but still use general method that accept any animal.

  3. I tried changing type: 'dog' | 'cat' to type: string - does not work. I would expect 'dog' string is subtype of general string type but it's not. On the other hand even if it works it wouldn't be enough - sometimes I know that my app accepts only dogs and cats not any other animals.

Thanks for reading and I hope I can get some help from you guys! Here's live version: Try Flow - live example






type Animal = 
id: number,
name: string,
type: 'dog' ;

type Dog =
id: number,
name: string,
type: 'dog',
color: string
;

function printAnimal(animal: Animal): string
return `$animal.type: $animal.name`;


const buddy: Dog =
id: 1,
name: 'Buddy',
type: 'dog',
color: 'black'


printAnimal(buddy);





type Animal = 
id: number,
name: string,
type: 'dog' ;

type Dog =
id: number,
name: string,
type: 'dog',
color: string
;

function printAnimal(animal: Animal): string
return `$animal.type: $animal.name`;


const buddy: Dog =
id: 1,
name: 'Buddy',
type: 'dog',
color: 'black'


printAnimal(buddy);






javascript flowtype






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 12 at 10:17









Ernest Nowacki

21616




21616







  • 2




    I've been able to find solution by actually specifing two explicit type definitions: for cat and dog and then create a type out of those two with disjoint union. Here's live version. Still looking for better ways!
    – Ernest Nowacki
    Nov 12 at 11:10










  • after playing around a bit, I found this cyclic weirdness to be working: live. Well kind of, because imo. this animal.color should throw, as Cat doesn't implement a color
    – Thomas
    Nov 14 at 12:08











  • Thanks for your input @Thomas ! It's definitely nice that your solution is not throwing error however I don't like cyclomatic complexity - it looks like Animal now needs Cat type to be defined and Cat type need Animal type to be defined. So for now I'm rolling with type Animal = Cat | Dog.
    – Ernest Nowacki
    Nov 16 at 10:41












  • 2




    I've been able to find solution by actually specifing two explicit type definitions: for cat and dog and then create a type out of those two with disjoint union. Here's live version. Still looking for better ways!
    – Ernest Nowacki
    Nov 12 at 11:10










  • after playing around a bit, I found this cyclic weirdness to be working: live. Well kind of, because imo. this animal.color should throw, as Cat doesn't implement a color
    – Thomas
    Nov 14 at 12:08











  • Thanks for your input @Thomas ! It's definitely nice that your solution is not throwing error however I don't like cyclomatic complexity - it looks like Animal now needs Cat type to be defined and Cat type need Animal type to be defined. So for now I'm rolling with type Animal = Cat | Dog.
    – Ernest Nowacki
    Nov 16 at 10:41







2




2




I've been able to find solution by actually specifing two explicit type definitions: for cat and dog and then create a type out of those two with disjoint union. Here's live version. Still looking for better ways!
– Ernest Nowacki
Nov 12 at 11:10




I've been able to find solution by actually specifing two explicit type definitions: for cat and dog and then create a type out of those two with disjoint union. Here's live version. Still looking for better ways!
– Ernest Nowacki
Nov 12 at 11:10












after playing around a bit, I found this cyclic weirdness to be working: live. Well kind of, because imo. this animal.color should throw, as Cat doesn't implement a color
– Thomas
Nov 14 at 12:08





after playing around a bit, I found this cyclic weirdness to be working: live. Well kind of, because imo. this animal.color should throw, as Cat doesn't implement a color
– Thomas
Nov 14 at 12:08













Thanks for your input @Thomas ! It's definitely nice that your solution is not throwing error however I don't like cyclomatic complexity - it looks like Animal now needs Cat type to be defined and Cat type need Animal type to be defined. So for now I'm rolling with type Animal = Cat | Dog.
– Ernest Nowacki
Nov 16 at 10:41




Thanks for your input @Thomas ! It's definitely nice that your solution is not throwing error however I don't like cyclomatic complexity - it looks like Animal now needs Cat type to be defined and Cat type need Animal type to be defined. So for now I'm rolling with type Animal = Cat | Dog.
– Ernest Nowacki
Nov 16 at 10:41












1 Answer
1






active

oldest

votes


















1














You have to make the Animal type an interface since it's describing your types implementations as a "parent". And it would make sense if you enforce it by extending your Dog type via a union since that's the point of using typings to reach a stronger type-checking.



This can be written like this:






/* @flow */

interface Animal
id: number,
name: string,
type: 'dog' ;

type Dog = Animal &
type: 'dog',
color: string
;

function printAnimal(animal: Animal): string
return `$animal.type: $animal.name`;


const buddy: Dog =
id: 1,
name: 'Buddy',
type: 'dog',
color: 'black'


printAnimal(buddy);








share|improve this answer




















    Your Answer






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

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

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

    else
    createEditor();

    );

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



    );













    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53260023%2fflowtype-extend-object-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









    1














    You have to make the Animal type an interface since it's describing your types implementations as a "parent". And it would make sense if you enforce it by extending your Dog type via a union since that's the point of using typings to reach a stronger type-checking.



    This can be written like this:






    /* @flow */

    interface Animal
    id: number,
    name: string,
    type: 'dog' ;

    type Dog = Animal &
    type: 'dog',
    color: string
    ;

    function printAnimal(animal: Animal): string
    return `$animal.type: $animal.name`;


    const buddy: Dog =
    id: 1,
    name: 'Buddy',
    type: 'dog',
    color: 'black'


    printAnimal(buddy);








    share|improve this answer

























      1














      You have to make the Animal type an interface since it's describing your types implementations as a "parent". And it would make sense if you enforce it by extending your Dog type via a union since that's the point of using typings to reach a stronger type-checking.



      This can be written like this:






      /* @flow */

      interface Animal
      id: number,
      name: string,
      type: 'dog' ;

      type Dog = Animal &
      type: 'dog',
      color: string
      ;

      function printAnimal(animal: Animal): string
      return `$animal.type: $animal.name`;


      const buddy: Dog =
      id: 1,
      name: 'Buddy',
      type: 'dog',
      color: 'black'


      printAnimal(buddy);








      share|improve this answer























        1












        1








        1






        You have to make the Animal type an interface since it's describing your types implementations as a "parent". And it would make sense if you enforce it by extending your Dog type via a union since that's the point of using typings to reach a stronger type-checking.



        This can be written like this:






        /* @flow */

        interface Animal
        id: number,
        name: string,
        type: 'dog' ;

        type Dog = Animal &
        type: 'dog',
        color: string
        ;

        function printAnimal(animal: Animal): string
        return `$animal.type: $animal.name`;


        const buddy: Dog =
        id: 1,
        name: 'Buddy',
        type: 'dog',
        color: 'black'


        printAnimal(buddy);








        share|improve this answer












        You have to make the Animal type an interface since it's describing your types implementations as a "parent". And it would make sense if you enforce it by extending your Dog type via a union since that's the point of using typings to reach a stronger type-checking.



        This can be written like this:






        /* @flow */

        interface Animal
        id: number,
        name: string,
        type: 'dog' ;

        type Dog = Animal &
        type: 'dog',
        color: string
        ;

        function printAnimal(animal: Animal): string
        return `$animal.type: $animal.name`;


        const buddy: Dog =
        id: 1,
        name: 'Buddy',
        type: 'dog',
        color: 'black'


        printAnimal(buddy);








        /* @flow */

        interface Animal
        id: number,
        name: string,
        type: 'dog' ;

        type Dog = Animal &
        type: 'dog',
        color: string
        ;

        function printAnimal(animal: Animal): string
        return `$animal.type: $animal.name`;


        const buddy: Dog =
        id: 1,
        name: 'Buddy',
        type: 'dog',
        color: 'black'


        printAnimal(buddy);





        /* @flow */

        interface Animal
        id: number,
        name: string,
        type: 'dog' ;

        type Dog = Animal &
        type: 'dog',
        color: string
        ;

        function printAnimal(animal: Animal): string
        return `$animal.type: $animal.name`;


        const buddy: Dog =
        id: 1,
        name: 'Buddy',
        type: 'dog',
        color: 'black'


        printAnimal(buddy);






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 19 at 2:44









        Ivan Gabriele

        3,29622444




        3,29622444



























            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.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • 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%2f53260023%2fflowtype-extend-object-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







            這個網誌中的熱門文章

            How to read a connectionString WITH PROVIDER in .NET Core?

            Node.js Script on GitHub Pages or Amazon S3

            Museum of Modern and Contemporary Art of Trento and Rovereto