Skip to content

TypeScript support #1234

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

Closed
wants to merge 24 commits into from
Closed

Conversation

devongovett
Copy link
Contributor

@devongovett devongovett commented Apr 19, 2019

Related: #282.

This PR adds TypeScript support to documentationjs, using Babel 7's TypeScript parsing support. This is enabled automatically when a file with a .ts or .tsx extension is seen. Similar to the Flow support, TypeScript annotations are converted to Doctrine compatible values. A wrapper function to handle all Babel-parsed type annotations and convert to Doctrine was added for this.

In addition to converting types, inference was added for most TypeScript constructs including access modifiers, abstract classes, getters/setters, function/method params and return types, type alias and interface properties, etc.

There are a few advanced constructs in TypeScript that cannot be directly converted to Doctrine types. I'm not really sure what to do about them:

  • Type parameters (generics)
  • Intersection types
  • Conditional types
  • Inferred types
  • Indexed types
  • Mapped types
  • Import types
  • Type queries and predicates

Perhaps we can start with basic support, and figure out how to get support for these in after the initial implementation is complete. Some of these also have Flow equivalents which are already unhandled by documentationjs.

Full list of TypeScript AST nodes (from babel) is below. Some of them can still be added, others like the above listed categories will be more challenging due to limitations of Doctrine, and others may not be necessary for a documentation generator to support.

  • TSParameterProperty
  • TSDeclareFunction
  • TSDeclareMethod
  • TSQualifiedName
  • TSCallSignatureDeclaration
  • TSPropertySignature
    • optional
    • readonly
    • typeAnnotation
  • TSMethodSignature
    • typeParameters
    • parameters
    • typeAnnotation
    • optional
  • TSIndexSignature
  • TSAnyKeyword
  • TSUnknownKeyword
  • TSNumberKeyword
  • TSObjectKeyword
  • TSBooleanKeyword
  • TSStringKeyword
  • TSSymbolKeyword
  • TSVoidKeyword
  • TSUndefinedKeyword
  • TSNullKeyword
  • TSNeverKeyword
  • TSThisType
  • TSFunctionType
    • typeParameters
    • parameters
    • typeAnnotation
  • TSConstructorType
    • typeParameters
    • parameters
    • typeAnnotation
  • TSTypeReference
    • typeName
    • typeParameters
  • TSTypePredicate
  • TSTypeQuery
  • TSTypeLiteral
  • TSArrayType
  • TSTupleType
  • TSOptionalType
  • TSRestType
  • TSUnionType
  • TSIntersectionType
  • TSConditionalType
  • TSInferType
  • TSParenthesizedType
  • TSTypeOperator
  • TSIndexedAccessType
  • TSMappedType
  • TSLiteralType
  • TSExpressionWithTypeArguments
  • TSInterfaceDeclaration
    • typeParameters
    • extends
    • body
  • TSInterfaceBody
  • TSTypeAliasDeclaration
    • typeParameters
    • typeAnnotation
  • TSAsExpression
  • TSTypeAssertion
  • TSEnumDeclaration
  • TSEnumMember
  • TSModuleDeclaration
  • TSModuleBlock
  • TSImportType
  • TSImportEqualsDeclaration
  • TSExternalModuleReference
  • TSNonNullExpression
  • TSExportAssignment
  • TSNamespaceExportDeclaration
  • TSTypeAnnotation
  • TSTypeParameterInstantiation
  • TSTypeParameterDeclaration
  • TSTypeParameter

Additional JSDoc tags with equivalents in TypeScript (and Flow) that are not yet supported:

  • @implements
  • @enum

@devongovett devongovett mentioned this pull request Apr 19, 2019
@devongovett
Copy link
Contributor Author

I have changed interfaces to use members instead of properties. This allows interfaces to work more like classes, and support annotations for method members, etc. whereas properties were quite limited. This should fix #742 as well.

I left type aliases the same (as records with properties), and that seems to make sense to me since interfaces are more often used to describe a class whereas types are more similar to type definitions and might be inlined into docs (e.g. as parameter types).

@devongovett
Copy link
Contributor Author

Ok, I think this is pretty much ready for review! I added @enum and @implements support as well, plus inference for Flow and TS. The remaining AST nodes in the todo list above either don't have an equivalent in doctrine, or are relatively obscure syntax. I think what I've implemented so far is a good place to start - we can add additional features later as they become necessary.

The one major missing feature is generics. There is the @template tag from Google Closure, which is not a standard JSDoc thing, but it's the closest tag I could find that we could support. We'd need to define the schema and add inference from flow/typescript as well. https://github.com/google/closure-compiler/wiki/Generic-Types

@devongovett devongovett marked this pull request as ready for review April 22, 2019 18:08
@devongovett devongovett changed the title [WIP] TypeScript support TypeScript support Apr 22, 2019
@tmcw
Copy link
Member

tmcw commented Apr 22, 2019

Amazing! I'm at ye olde day job right now, but I'll take a look at this tonight.

@tmcw
Copy link
Member

tmcw commented Apr 25, 2019

Rebased and merged in #1236!

For folks using documentation.js 'off-the-shelf', noting that this won't immediately show some new features like 'implements' in Markdown or the HTML mode - that's a TODO. But - TypeScript! Thanks @devongovett!

@devongovett
Copy link
Contributor Author

Awesome, thanks for reviewing such a large PR so quickly!

@diegohaz
Copy link

diegohaz commented Jun 7, 2019

Should this work seamlessly if I run documentation readme src --section=API with a src/index.ts or do I need to do anything else?

@tmcw
Copy link
Member

tmcw commented Jun 7, 2019

Please open new issues if you have questions or bugs to report - this is the PR for the feature.

@kripod
Copy link
Contributor

kripod commented Aug 20, 2019

Thank you for the fantastic work! Unfortunately, readonly seems to break parsing when used in a return type, e.g.: function test(): readonly string[] { return []; }

readonly tuples (added in TypeScript 3.4, just like readonly arrays) don't seem to work, either.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants