Mapped record causes type any when recursiveTypescript: How to define type for a function callback (as any function type, not universal any) used in a method parameterHow do I prevent the error “Index signature of object type implicitly has an 'any' type” when compiling typescript with noImplicitAny flag enabled?Import class in definition file (*d.ts)Typescript type mapping to expect an object where every property is of a given typeTypeScript: Using Mapped Types with GenericsTypeScript: Conditional Mapped Types and Generic Type ParametersReflect and map typed argument shape in typescript?Enzyme change another input fieldA type-safe way to recursively map a class to its JSON representationHow can I get mapped type names for a graphQL type using type-graphql

A steel cutting sword?

What was the idiom for something that we take without a doubt?

Is "cool" appropriate or offensive to use in IMs?

Pirate democracy at its finest

Could a 19.25mm revolver actually exist?

What are the mechanical differences between the uncommon Medallion of Thoughts and the rare Potion of Mind Reading?

NIntegrate doesn't evaluate

Why didn't Project Mercury advance to an orbital flight on their second mission?

Sitecore 9.0 works with solr 7.2.1?

Find the names of these countries

Have 1.5% of all nuclear reactors ever built melted down?

What are the real benefits of using Salesforce DX?

Why does this if-statement combining assignment and an equality check return true?

Caught student / friend cheating on the final exam that I proctored

What is Theresa May waiting for?

The usage of "run a mile" in a sentence

Make 24 using exactly three 3s

Teacher help me explain this to my students

Installed Tankless Water Heater - Internet loss when active

The art of clickbait captions

How to know if a folder is a symbolic link?

How to patch glass cuts in a bicycle tire?

Why aren't space telescopes put in GEO?

How do I partition a matrx into blocks and replace zeros with dots?



Mapped record causes type any when recursive


Typescript: How to define type for a function callback (as any function type, not universal any) used in a method parameterHow do I prevent the error “Index signature of object type implicitly has an 'any' type” when compiling typescript with noImplicitAny flag enabled?Import class in definition file (*d.ts)Typescript type mapping to expect an object where every property is of a given typeTypeScript: Using Mapped Types with GenericsTypeScript: Conditional Mapped Types and Generic Type ParametersReflect and map typed argument shape in typescript?Enzyme change another input fieldA type-safe way to recursively map a class to its JSON representationHow can I get mapped type names for a graphQL type using type-graphql






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








0















I'm using mapped types to transform a data structure, which works as expected except when there is a recursive field.



Is there a way to prevent it from becoming type any?



type DataType<T extends Record<keyof T, Obj<any, any>>> = 
[P in keyof T]: T[P]['data']


// I need to be able to pass in a Data generic
// to this object
class Obj<
Data extends DataType<T>,
T extends Record<keyof Data, Obj<any, any>>
>
constructor(public fields: T)

public data: Data


const recursive = new Obj(
// With this field, the 'recursive' variable becomes type 'any'
get query()
return recursive
,
test: new Obj()
)

// Without recursive field it works as expected
const nonRecursive = new Obj( test: new Obj() )
nonRecursive.data.test // okay









share|improve this question




























    0















    I'm using mapped types to transform a data structure, which works as expected except when there is a recursive field.



    Is there a way to prevent it from becoming type any?



    type DataType<T extends Record<keyof T, Obj<any, any>>> = 
    [P in keyof T]: T[P]['data']


    // I need to be able to pass in a Data generic
    // to this object
    class Obj<
    Data extends DataType<T>,
    T extends Record<keyof Data, Obj<any, any>>
    >
    constructor(public fields: T)

    public data: Data


    const recursive = new Obj(
    // With this field, the 'recursive' variable becomes type 'any'
    get query()
    return recursive
    ,
    test: new Obj()
    )

    // Without recursive field it works as expected
    const nonRecursive = new Obj( test: new Obj() )
    nonRecursive.data.test // okay









    share|improve this question
























      0












      0








      0


      1






      I'm using mapped types to transform a data structure, which works as expected except when there is a recursive field.



      Is there a way to prevent it from becoming type any?



      type DataType<T extends Record<keyof T, Obj<any, any>>> = 
      [P in keyof T]: T[P]['data']


      // I need to be able to pass in a Data generic
      // to this object
      class Obj<
      Data extends DataType<T>,
      T extends Record<keyof Data, Obj<any, any>>
      >
      constructor(public fields: T)

      public data: Data


      const recursive = new Obj(
      // With this field, the 'recursive' variable becomes type 'any'
      get query()
      return recursive
      ,
      test: new Obj()
      )

      // Without recursive field it works as expected
      const nonRecursive = new Obj( test: new Obj() )
      nonRecursive.data.test // okay









      share|improve this question














      I'm using mapped types to transform a data structure, which works as expected except when there is a recursive field.



      Is there a way to prevent it from becoming type any?



      type DataType<T extends Record<keyof T, Obj<any, any>>> = 
      [P in keyof T]: T[P]['data']


      // I need to be able to pass in a Data generic
      // to this object
      class Obj<
      Data extends DataType<T>,
      T extends Record<keyof Data, Obj<any, any>>
      >
      constructor(public fields: T)

      public data: Data


      const recursive = new Obj(
      // With this field, the 'recursive' variable becomes type 'any'
      get query()
      return recursive
      ,
      test: new Obj()
      )

      // Without recursive field it works as expected
      const nonRecursive = new Obj( test: new Obj() )
      nonRecursive.data.test // okay






      typescript






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Mar 24 at 3:56









      samddsamdd

      2,37421326




      2,37421326






















          1 Answer
          1






          active

          oldest

          votes


















          2














          Hmm, you're carrying around a lot of mutually referential generic types here, and without a use case and examples I admit I have almost no idea what's going on here and if this is really the best way to represent your data structure. I'd guess you could probably get away with a single type parameter like this:



          class Obj<T>

          constructor(public fields: [K in keyof T]: Obj<T[K]> )

          public data!: T



          But even if you do that you will still have the same issue, which gets exposed if you enable the stricter compiler options like --noImplicitAny or --strict. Then you will see that your definition of recursive gives you the following errors:




          'recursive' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.




          and




          'query' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.




          This is the intended behavior when the compiler cannot infer a type because it depends on itself in certain ways. The suggested way to deal with this is usually to give an explicit type annotation to one of the pieces to break the circularity. It's annoying because it forces you to redundantly write out typings to things that were previously inferred by the compiler, but I don't know if there's a good way to avoid that.



          Here's one way of doing it with the types as you have them:



          // explicit type
          interface RecursiveObj extends Obj<
          DataType<
          readonly query: RecursiveObj; test: Obj<, >;
          >, readonly query: RecursiveObj; test: Obj<, >; >


          const recursive = new Obj(
          // explicitly annotated return type
          get query(): RecursiveObj
          return recursive
          ,
          test: new Obj()
          ); // okay now


          And here's how I'd do it with the simplified Obj<T> type I listed above:



          // explicit type
          interface RecursiveData
          readonly query: RecursiveData,
          test:


          const recursive = new Obj(
          // explicitly annotated return type
          get query(): Obj<RecursiveData>
          return recursive
          ,
          test: new Obj()
          ); // okay now


          Okay, hope that helps. Good luck!






          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%2f55320592%2fmapped-record-causes-type-any-when-recursive%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









            2














            Hmm, you're carrying around a lot of mutually referential generic types here, and without a use case and examples I admit I have almost no idea what's going on here and if this is really the best way to represent your data structure. I'd guess you could probably get away with a single type parameter like this:



            class Obj<T>

            constructor(public fields: [K in keyof T]: Obj<T[K]> )

            public data!: T



            But even if you do that you will still have the same issue, which gets exposed if you enable the stricter compiler options like --noImplicitAny or --strict. Then you will see that your definition of recursive gives you the following errors:




            'recursive' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.




            and




            'query' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.




            This is the intended behavior when the compiler cannot infer a type because it depends on itself in certain ways. The suggested way to deal with this is usually to give an explicit type annotation to one of the pieces to break the circularity. It's annoying because it forces you to redundantly write out typings to things that were previously inferred by the compiler, but I don't know if there's a good way to avoid that.



            Here's one way of doing it with the types as you have them:



            // explicit type
            interface RecursiveObj extends Obj<
            DataType<
            readonly query: RecursiveObj; test: Obj<, >;
            >, readonly query: RecursiveObj; test: Obj<, >; >


            const recursive = new Obj(
            // explicitly annotated return type
            get query(): RecursiveObj
            return recursive
            ,
            test: new Obj()
            ); // okay now


            And here's how I'd do it with the simplified Obj<T> type I listed above:



            // explicit type
            interface RecursiveData
            readonly query: RecursiveData,
            test:


            const recursive = new Obj(
            // explicitly annotated return type
            get query(): Obj<RecursiveData>
            return recursive
            ,
            test: new Obj()
            ); // okay now


            Okay, hope that helps. Good luck!






            share|improve this answer



























              2














              Hmm, you're carrying around a lot of mutually referential generic types here, and without a use case and examples I admit I have almost no idea what's going on here and if this is really the best way to represent your data structure. I'd guess you could probably get away with a single type parameter like this:



              class Obj<T>

              constructor(public fields: [K in keyof T]: Obj<T[K]> )

              public data!: T



              But even if you do that you will still have the same issue, which gets exposed if you enable the stricter compiler options like --noImplicitAny or --strict. Then you will see that your definition of recursive gives you the following errors:




              'recursive' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.




              and




              'query' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.




              This is the intended behavior when the compiler cannot infer a type because it depends on itself in certain ways. The suggested way to deal with this is usually to give an explicit type annotation to one of the pieces to break the circularity. It's annoying because it forces you to redundantly write out typings to things that were previously inferred by the compiler, but I don't know if there's a good way to avoid that.



              Here's one way of doing it with the types as you have them:



              // explicit type
              interface RecursiveObj extends Obj<
              DataType<
              readonly query: RecursiveObj; test: Obj<, >;
              >, readonly query: RecursiveObj; test: Obj<, >; >


              const recursive = new Obj(
              // explicitly annotated return type
              get query(): RecursiveObj
              return recursive
              ,
              test: new Obj()
              ); // okay now


              And here's how I'd do it with the simplified Obj<T> type I listed above:



              // explicit type
              interface RecursiveData
              readonly query: RecursiveData,
              test:


              const recursive = new Obj(
              // explicitly annotated return type
              get query(): Obj<RecursiveData>
              return recursive
              ,
              test: new Obj()
              ); // okay now


              Okay, hope that helps. Good luck!






              share|improve this answer

























                2












                2








                2







                Hmm, you're carrying around a lot of mutually referential generic types here, and without a use case and examples I admit I have almost no idea what's going on here and if this is really the best way to represent your data structure. I'd guess you could probably get away with a single type parameter like this:



                class Obj<T>

                constructor(public fields: [K in keyof T]: Obj<T[K]> )

                public data!: T



                But even if you do that you will still have the same issue, which gets exposed if you enable the stricter compiler options like --noImplicitAny or --strict. Then you will see that your definition of recursive gives you the following errors:




                'recursive' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.




                and




                'query' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.




                This is the intended behavior when the compiler cannot infer a type because it depends on itself in certain ways. The suggested way to deal with this is usually to give an explicit type annotation to one of the pieces to break the circularity. It's annoying because it forces you to redundantly write out typings to things that were previously inferred by the compiler, but I don't know if there's a good way to avoid that.



                Here's one way of doing it with the types as you have them:



                // explicit type
                interface RecursiveObj extends Obj<
                DataType<
                readonly query: RecursiveObj; test: Obj<, >;
                >, readonly query: RecursiveObj; test: Obj<, >; >


                const recursive = new Obj(
                // explicitly annotated return type
                get query(): RecursiveObj
                return recursive
                ,
                test: new Obj()
                ); // okay now


                And here's how I'd do it with the simplified Obj<T> type I listed above:



                // explicit type
                interface RecursiveData
                readonly query: RecursiveData,
                test:


                const recursive = new Obj(
                // explicitly annotated return type
                get query(): Obj<RecursiveData>
                return recursive
                ,
                test: new Obj()
                ); // okay now


                Okay, hope that helps. Good luck!






                share|improve this answer













                Hmm, you're carrying around a lot of mutually referential generic types here, and without a use case and examples I admit I have almost no idea what's going on here and if this is really the best way to represent your data structure. I'd guess you could probably get away with a single type parameter like this:



                class Obj<T>

                constructor(public fields: [K in keyof T]: Obj<T[K]> )

                public data!: T



                But even if you do that you will still have the same issue, which gets exposed if you enable the stricter compiler options like --noImplicitAny or --strict. Then you will see that your definition of recursive gives you the following errors:




                'recursive' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.




                and




                'query' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.




                This is the intended behavior when the compiler cannot infer a type because it depends on itself in certain ways. The suggested way to deal with this is usually to give an explicit type annotation to one of the pieces to break the circularity. It's annoying because it forces you to redundantly write out typings to things that were previously inferred by the compiler, but I don't know if there's a good way to avoid that.



                Here's one way of doing it with the types as you have them:



                // explicit type
                interface RecursiveObj extends Obj<
                DataType<
                readonly query: RecursiveObj; test: Obj<, >;
                >, readonly query: RecursiveObj; test: Obj<, >; >


                const recursive = new Obj(
                // explicitly annotated return type
                get query(): RecursiveObj
                return recursive
                ,
                test: new Obj()
                ); // okay now


                And here's how I'd do it with the simplified Obj<T> type I listed above:



                // explicit type
                interface RecursiveData
                readonly query: RecursiveData,
                test:


                const recursive = new Obj(
                // explicitly annotated return type
                get query(): Obj<RecursiveData>
                return recursive
                ,
                test: new Obj()
                ); // okay now


                Okay, hope that helps. Good luck!







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Mar 25 at 1:08









                jcalzjcalz

                36k23253




                36k23253





























                    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%2f55320592%2fmapped-record-causes-type-any-when-recursive%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

                    Kamusi Yaliyomo Aina za kamusi | Muundo wa kamusi | Faida za kamusi | Dhima ya picha katika kamusi | Marejeo | Tazama pia | Viungo vya nje | UrambazajiKuhusu kamusiGo-SwahiliWiki-KamusiKamusi ya Kiswahili na Kiingerezakuihariri na kuongeza habari

                    Swift 4 - func physicsWorld not invoked on collision? The Next CEO of Stack OverflowHow to call Objective-C code from Swift#ifdef replacement in the Swift language@selector() in Swift?#pragma mark in Swift?Swift for loop: for index, element in array?dispatch_after - GCD in Swift?Swift Beta performance: sorting arraysSplit a String into an array in Swift?The use of Swift 3 @objc inference in Swift 4 mode is deprecated?How to optimize UITableViewCell, because my UITableView lags

                    Access current req object everywhere in Node.js ExpressWhy are global variables considered bad practice? (node.js)Using req & res across functionsHow do I get the path to the current script with Node.js?What is Node.js' Connect, Express and “middleware”?Node.js w/ express error handling in callbackHow to access the GET parameters after “?” in Express?Modify Node.js req object parametersAccess “app” variable inside of ExpressJS/ConnectJS middleware?Node.js Express app - request objectAngular Http Module considered middleware?Session variables in ExpressJSAdd properties to the req object in expressjs with Typescript