denoland / deno_doc

Documentation generator for Deno
MIT License
252 stars 55 forks source link

Show typedef-defined types in JS files #137

Open opiation opened 3 years ago

opiation commented 3 years ago

Types defined with @typedef are not displayed in console output under deno doc with the following deno version:

$ deno --version

deno 1.13.2 (release, x86_64-apple-darwin)
v8 9.3.345.11
typescript 4.3.5

For example,

// identity.js

/**
 * @template T
 * @typedef {Object} Identity
 * @property {<U>(f: (value: T) => U) => Identity<U>} map
 */

/**
 * @template T
 * @param {T} value
 * @return {Identity<T>}
 */
export function of(value) {
  return {
    map(f) {
      return of(f(value));
    }
  };
}
$ deno doc identity.js

function of(value)
  @template T
  @param {T} value
  @return {Identity<T>}

Importing the Identity type from a .ts file however shows that the type is indeed exported by the .js file.

// example.ts

import type { Identity } from './identity.js'; // works fine

It does not show up in deno doc identity.js though. If the type or interface were defined in a .ts file, it would appear in the output as:

// identity.ts

export interface Identity<T> {
  map<U>(f: (value: T) => U): Identity<U>
}
$ deno doc identity.ts

interface Identity<T>

  map(f: (value: T) => U): Identity<U>

Can types defined with JSDoc's @typedef be exposed by deno doc?

kitsonk commented 2 years ago

146 will be part of the problem, but we need to be able to represent "standalone" JSDoc blocks in the doc nodes.

That would just get a JSDoc block with the appropriate tags parsed out, but it wouldn't actually generate the same type understanding that currently gets parsed out, and it would be up to the consumer (doc website) to try to figure out how to represent this.

opiation commented 2 years ago

Hey @kitsonk, thanks for responding! My understanding of likely JS scenarios here are:

  1. Doc'ing a pure JS file with no type annotations (not quite as interesting but possibly relevant)
  2. Doc'ing a pure JS file with JSDoc type annotations
  3. Doc'ing a pure JS file with accompanying type definitions referenced
  4. Doc'ing a pure JS file with JSDoc type annotations and accompanying type definitions referenced

Do the above scenarios make sense with regard to this feature request?

146 will be part of the problem

If I understand this correctly, #146 should only affect scenario 4 because there might be competing type annotations, correct? If so, would it be fair to always select the type definitions and fallback to JSDoc type annotations when type definitions are unavailable for a particular value?

That would just get a JSDoc block with the appropriate tags parsed out, but it wouldn't actually generate the same type understanding that currently gets parsed out, and it would be up to the consumer (doc website) to try to figure out how to represent this.

Does this mean that JSDoc type annotations are not actually resolved to same type constructs as TS type annotations internally and this is part of the challenge? Sorry if this question is strange. I am not at al familiar with internal type node representations.

kitsonk commented 2 years ago

The use cases make sense. They always have to me.

Does this mean that JSDoc type annotations are not actually resolved to same type constructs as TS type annotations internally and this is part of the challenge?

In Deno CLI, all type checking is done by the TypeScript compiler (tsc) that is embedded into the Deno CLI. This is what also powers the language server when doing a hover in the IDE to get type information. deno_doc uses a Rust based library called swc to parse the syntax of the document. It is what we use in the Deno CLI to also transpile TypeScript code to JavaScript code. swc can "read" explicit types and parse them out into a structure which we can use to provide documentation. Basically it just takes strings and converts it into something that can be procedural read and manipulated (AST).

The TypeScript compiler reads the JSDoc and overlays those types on-top of the JavaScript syntax and then enforces those types when type checking.

What I am expressing is that #146 basically parses out a lot of that code in a structured way, but it doesn't overlay that on the syntax and marry up the types. That is still desired, but is a non-trivial amount of work.