jsdoctypeparser
The parser can parse:
- JSDoc type expressions
foo.bar
,String[]
- Closure Compiler type expressions
Array<string>
,function(arg1, arg2): ret
- some Typescript types
(x: number) => string
,typeof x
,import("./some-module")
- Complex type expressions
Array<Array<string>>
,function(function(Function))
Live demo
The live demo is available.
Usage (Programmatic)
Parsing
const parse = ; const ast = ;
The ast
becomes:
See the AST specifications.
Publishing
We can stringify the AST nodes by using publish
.
const publish = ; const ast = type: 'GENERIC' subject: type: 'NAME' name: 'Array' objects: type: 'NAME' name: 'MyClass' ; const string = ;
The string
becomes:
"Array<MyClass>"
Custom publishing
We can change the stringification strategy by using the 2nd parameter of publish(node, publisher)
.
The publisher
MUST have handlers for all node types (see lib/NodeType.js
).
And we can override default behavior by using createDefaultPublisher
.
const publish createDefaultPublisher = ; const ast = type: 'NAME' name: 'MyClass'; const customPublisher = ;customPublisher `<a href="./types/.html"></a>`; const string = ;
The string
becomes:
MyClass
Traversing
We can traverse the AST by using traverse
.
This function takes 3 parameters (a node and an onEnter handler, an onLeave handler).
The handlers take a visiting node.
const parse traverse = ;const ast = ; { console;} { console;} ;
The output will be:
enter GENERIC null null
enter NAME subject GENERIC
leave NAME subject GENERIC
enter RECORD objects GENERIC
enter RECORD_ENTRY entries RECORD
enter FUNCTION value RECORD_ENTRY
leave FUNCTION value RECORD_ENTRY
leave RECORD_ENTRY entries RECORD
enter RECORD_ENTRY entries RECORD
enter MEMBER value RECORD_ENTRY
enter MEMBER owner MEMBER
enter NAME owner MEMBER
leave NAME owner MEMBER
leave MEMBER owner MEMBER
leave MEMBER value RECORD_ENTRY
leave RECORD_ENTRY entries RECORD
leave RECORD objects GENERIC
leave GENERIC null null
AST Specifications
NAME
Example:
/** * @type */
Structure:
"type": "NAME" "name": string
MEMBER
Example:
/** * @type * @type */
Structure:
"type": "MEMBER" "name": string "quoteStyle": "none" "owner": node "hasEventPrefix": boolean
INNER_MEMBER
Example:
/** * @type */
Structure:
"type": "INNER_MEMBER" "name": string "quoteStyle": "none" "owner": node "hasEventPrefix": boolean
INSTANCE_MEMBER
Example:
/** * @type {owner#name} */
Structure:
"type": "INSTANCE_MEMBER" "name": string "quoteStyle": "none" "owner": node "hasEventPrefix": boolean
UNION
Example:
/** * @type * @type */
Structure:
"type": "UNION" "left": node "right": node
INTERSECTION
Example:
/** * @type {left&right} * @type {(left&right)} */
Structure:
"type": "INTERSECTION" "left": node "right": node
RECORD
Example:
/** * @type {{}} * @type {{ key: value }} * @type {{ key: value, anyKey }} */
Structure:
"type": "RECORD" "entries": recordEntryNode recordEntryNode ...
RECORD_ENTRY
Structure:
"type": "RECORD_ENTRY" "key": string "value":
GENERIC
Example:
/** * @type * @type */
Structure:
"type": "GENERIC" "subject": node "objects": node node ... "meta": "syntax": "ANGLE_BRACKET" or "ANGLE_BRACKET_WITH_DOT" or "SQUARE_BRACKET"
FUNCTION
Example:
/** * @type * @type * @type {function(this: Context)} * @type {function(new: Class)} */
Structure:
"type": "FUNCTION" "params": node node ... "returns": "new": "this":
OPTIONAL
Example:
/** * @type */
Structure:
"type": "OPTIONAL" "value": node "meta": "syntax": "PREFIX_EQUALS_SIGN" or "SUFFIX_EQUALS_SIGN"
NULLABLE
Example:
/** * @type */
Structure:
"type": "NULLABLE" "value": node "meta": "syntax": "PREFIX_QUESTION_MARK" or "SUFFIX_QUESTION_MARK"
NOT_NULLABLE
Example:
/** * @type */
Structure:
"type": "NOT_NULLABLE" "value": node "meta": "syntax": "PREFIX_BANG" or "SUFFIX_BANG"
VARIADIC
Example:
/** * @type * @type {Variadic...} * @type */
Structure:
"type": "VARIADIC" "value": "meta": "syntax": "PREFIX_DOTS" or "SUFFIX_DOTS" or "ONLY_DOTS"
MODULE
Example:
/** * @type {module:path/to/file.Module} */
Structure:
"type": "MODULE" "value": node
FILE_PATH
Example:
/** * @type {module:path/to/file.Module} * ^^^^^^^^^^^^ */
Structure:
"type": "FILE_PATH" "path": string
EXTERNAL
Example:
/** * @type {external:External} */
Structure:
"type": "EXTERNAL" "value": node
STRING_VALUE
Example:
/** * @type {"abc"} * @type {"can\"escape"} */
Structure:
"type": "STRING_VALUE" "quoteStyle": "double" "string": string
NUMBER_VALUE
Example:
/** * @type {123} * @type {0b11} * @type {0o77} * @type {0xff} */
Structure:
"type": "NUMBER_VALUE" "number": string
ANY
Example:
/** * @type */
Structure:
"type": "ANY"
UNKNOWN
Example:
/** * @type */
Structure:
"type": "UNKNOWN"
PARENTHESIS
Example:
/** * @type */
Structure:
"type": "PARENTHESIS" "value": node
Others
We can use a parenthesis to change operator orders.
/** * @type {(module:path/to/file.js).foo} */
Usage (CLI)
To parse a type into a JSON structure, you may pass a string argument containing the structure to parse (with the JSON results equivalent to the parsing example above):
jsdoctypeparser 'Array<MyClass>'
Note: There is no need to prefix the path to the jsdoctypeparser
binary,
e.g., with ./node_modules/.bin/
when you are running within one of the
package.json
scripts
or if you have installed the package globally.