Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeScript support #325

Closed
thebuilder opened this issue Feb 8, 2019 · 4 comments · Fixed by #348
Closed

TypeScript support #325

thebuilder opened this issue Feb 8, 2019 · 4 comments · Fixed by #348

Comments

@thebuilder
Copy link

Let's get react-docgen working with TypeScript. What will it take?
recast added support for TypeScript in 2018, and from #316 it looks like @jquense has been working on getting the parser integrated with react-docgen.

I haven't worked with recast, and I'm not sure how different the output is between Flow and TS.
But the the actual types are very similar. Here's the example from the Readme in TypeScript.
The only real change i did was changing subvalue: ?boolean to subvalue: boolean | null, which seems like the way to make values nullable.

Input

import React, { Component } from 'react';

type Props = {
  /** Description of prop "foo". */
  primitive: number
  /** Description of prop "bar". */
  literalsAndUnion: 'string' | 'otherstring' | number
  arr: Array<any>
  func?: (value: string) => void
  noParameterName?: string => void
  obj?: { subvalue: boolean | null }
};

/**
 * General component description.
 */
export default class MyComponent extends Component<Props> {
  render() {
    // ...
  }
}

Output

All flow types are currently exported under their own key "flowType". Following this structure, it would seem obvious to just add a new "typeScript" key?

{
  "description":"General component description.",
  "props":{
    "primitive":{
      "typeScript":{ "name":"number" },
      "required":true,
      "description":"Description of prop \"foo\"."
    },
    "literalsAndUnion":{
      "typeScript":{
        "name":"union",
        "raw":"'string' | 'otherstring' | number",
        "elements":[
          { "name":"literal", "value":"'string'" },
          { "name":"literal", "value":"'otherstring'" },
          { "name":"number" }
        ]
      },
      "required":true,
      "description":"Description of prop \"bar\"."
    },
    "arr":{
      "typeScript":{
        "name":"Array",
        "elements":[
          { "name":"any" }
        ],
        "raw":"Array<any>"
      },
      "required":true
    },
    "func":{
      "typeScript":{
        "name":"signature",
        "type":"function",
        "raw":"(value: string) => void",
        "signature":{
          "arguments":[
            { "name":"value", "type":{ "name":"string" } }
          ],
          "return":{ "name":"void" }
        }
      },
      "required":false
    },
    "noParameterName":{
      "typeScript":{
        "name":"signature",
        "type":"function",
        "raw":"string => void",
        "signature":{
          "arguments":[
            { "name":"", "type":{ "name":"string" } }
          ],
          "return":{ "name":"void" }
        }
      },
      "required":false
    },
    "obj":{
      "typeScript":{
        "name":"signature",
        "type":"object",
        "raw":"{ subvalue: ?boolean }",
        "signature":{
          "properties":[
            {
              "key":"subvalue",
              "value":{
                "name":"boolean",
                "nullable":true,
                "required":true
              }
            }
          ]
        }
      },
      "required":false
    }
  }
}
@danez
Copy link
Collaborator

danez commented Feb 8, 2019

Maybe it would also be possible to remove recast all together. The only reason why we use recast I guess is because we print some of the input code into the raw fields. see also #237.

But anyway typescript support would be nice and I think @jquense wanted/is working on that.

@fkling
Copy link
Member

fkling commented Feb 9, 2019

I'm all for reducing the number of dependencies, but we also use recast's ability to resolve identifiers to their value expressions, i.e.

https://github.com/reactjs/react-docgen/blob/master/src/utils/resolveToValue.js#L156

It would be good to compare the differences between the Typescript and Flow ASTs. I'd assume that recast provides some abstraction over them, but not sure.

@jquense
Copy link
Collaborator

jquense commented Feb 9, 2019

Recast traditional my makes stuff like resolveToValue easier than straight Babel, but the current babel API is better nowadays. Nodes have a .resolve that do the heavy lifting of binding traversal. And even without it I've written pure Babel versions a few times so I'd be happy to help there.

Honestly I'd like to remove recast, if only because it avoids a context shift between AST tools I use regularly :P

As for typescript I do think recast is probably abstracting the differences, the plain AST from babel attempts to match the actual typescript AST nodes for annotations which are fairly different from flows

@devongovett
Copy link
Contributor

I am working on TypeScript support here: #348. If you're interested in helping out with testing, please feel free to leave feedback on the PR!

@danez danez closed this as completed in #348 May 3, 2019
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jul 28, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants