What is jsdoctypeparser?
The jsdoctypeparser npm package is a tool for parsing and manipulating JSDoc type expressions. It allows developers to parse JSDoc type strings into an abstract syntax tree (AST) and then manipulate or analyze these types programmatically.
What are jsdoctypeparser's main functionalities?
Parsing JSDoc Type Strings
This feature allows you to parse a JSDoc type string into an abstract syntax tree (AST). The code sample demonstrates how to parse the type string 'Array.<string>' and output the resulting AST.
const { parse } = require('jsdoctypeparser');
const typeString = 'Array.<string>';
const ast = parse(typeString);
console.log(JSON.stringify(ast, null, 2));
Stringifying AST Back to JSDoc Type String
This feature allows you to convert an AST back into a JSDoc type string. The code sample shows how to parse a type string into an AST and then convert it back to a string.
const { parse, stringify } = require('jsdoctypeparser');
const typeString = 'Array.<string>';
const ast = parse(typeString);
const newTypeString = stringify(ast);
console.log(newTypeString);
Handling Complex Type Expressions
This feature demonstrates the ability to handle complex JSDoc type expressions. The code sample parses a complex type string representing an object with properties of different types.
const { parse } = require('jsdoctypeparser');
const complexTypeString = '{a: number, b: string|boolean}';
const ast = parse(complexTypeString);
console.log(JSON.stringify(ast, null, 2));
Other packages similar to jsdoctypeparser
doctrine
Doctrine is a popular library for parsing JSDoc comments, including type expressions. It provides a more comprehensive solution for parsing entire JSDoc comments, not just type strings. Compared to jsdoctypeparser, Doctrine offers broader functionality but may be more complex to use if you only need to parse type expressions.
comment-parser
Comment-parser is a library for parsing JavaScript comments, including JSDoc comments. It focuses on extracting and parsing comments from source code, including type annotations. While it provides similar functionality for parsing JSDoc types, it is more focused on the overall comment structure rather than just type expressions.
jsdoctypeparser

The parser can parse:
Live demo
The live demo is available.
Usage (Programmatic)
Parsing
const {parse} = require('jsdoctypeparser');
const ast = parse('Array<MyClass>');
The ast
becomes:
{
"type": "GENERIC",
"subject": {
"type": "NAME",
"name": "Array"
},
"objects": [
{
"type": "NAME",
"name": "MyClass"
}
],
"meta": {
"syntax": "ANGLE_BRACKET"
}
}
See the AST specifications.
Publishing
We can stringify the AST nodes by using publish
.
const {publish} = require('jsdoctypeparser');
const ast = {
type: 'GENERIC',
subject: {
type: 'NAME',
name: 'Array'
},
objects: [
{
type: 'NAME',
name: 'MyClass'
}
]
};
const string = publish(ast);
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} = require('jsdoctypeparser');
const ast = {
type: 'NAME',
name: 'MyClass',
};
const customPublisher = createDefaultPublisher();
customPublisher.NAME = (node, pub) =>
`<a href="./types/${node.name}.html">${node.name}</a>`;
const string = publish(ast, customPublisher);
The string
becomes:
<a href="./types/MyClass.html">MyClass</a>
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} = require('jsdoctypeparser');
const ast = parse('Array<{ key1: function(), key2: A.B.C }>');
function onEnter(node, parentName, parentNode) {
console.log('enter', node.type, parentName, parentNode.type);
}
function onLeave(node, parentName, parentNode) {
console.log('leave', node.type, parentName, parentNode.type);
}
traverse(ast, onEnter, onLeave);
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:
Structure:
{
"type": "NAME",
"name": string
}
MEMBER
Example:
Structure:
{
"type": "MEMBER",
"name": string,
"quoteStyle": "none",
"owner": node,
"hasEventPrefix": boolean
}
INNER_MEMBER
Example:
Structure:
{
"type": "INNER_MEMBER",
"name": string,
"quoteStyle": "none",
"owner": node,
"hasEventPrefix": boolean
}
INSTANCE_MEMBER
Example:
Structure:
{
"type": "INSTANCE_MEMBER",
"name": string,
"quoteStyle": "none",
"owner": node,
"hasEventPrefix": boolean
}
UNION
Example:
Structure:
{
"type": "UNION",
"left": node,
"right": node
}
INTERSECTION
Example:
Structure:
{
"type": "INTERSECTION",
"left": node,
"right": node
}
RECORD
Example:
Structure:
{
"type": "RECORD",
"entries": [
recordEntryNode,
recordEntryNode,
...
]
}
RECORD_ENTRY
Structure:
{
"type": "RECORD_ENTRY",
"key": string,
"value": node (or null)
}
GENERIC
Example:
Structure:
{
"type": "GENERIC",
"subject": node,
"objects": [
node,
node,
...
],
"meta": {
"syntax": ("ANGLE_BRACKET" or "ANGLE_BRACKET_WITH_DOT" or "SQUARE_BRACKET")
}
}
FUNCTION
Example:
Structure:
{
"type": "FUNCTION",
"params": [
node,
node,
...
],
"returns": node (or null),
"new": node (or null),
"this": node (or null)
}
OPTIONAL
Example:
Structure:
{
"type": "OPTIONAL",
"value": node,
"meta": {
"syntax": ("PREFIX_EQUALS_SIGN" or "SUFFIX_EQUALS_SIGN")
}
}
NULLABLE
Example:
Structure:
{
"type": "NULLABLE",
"value": node,
"meta": {
"syntax": ("PREFIX_QUESTION_MARK" or "SUFFIX_QUESTION_MARK")
}
}
NOT_NULLABLE
Example:
Structure:
{
"type": "NOT_NULLABLE",
"value": node,
"meta": {
"syntax": ("PREFIX_BANG" or "SUFFIX_BANG")
}
}
VARIADIC
Example:
Structure:
{
"type": "VARIADIC",
"value": node (or null),
"meta": {
"syntax": ("PREFIX_DOTS" or "SUFFIX_DOTS" or "ONLY_DOTS")
}
}
MODULE
Example:
Structure:
{
"type": "MODULE",
"value": node
}
FILE_PATH
Example:
Structure:
{
"type": "FILE_PATH",
"path": string
}
EXTERNAL
Example:
Structure:
{
"type": "EXTERNAL",
"value": node
}
STRING_VALUE
Example:
Structure:
{
"type": "STRING_VALUE",
"quoteStyle": "double",
"string": string
}
NUMBER_VALUE
Example:
Structure:
{
"type": "NUMBER_VALUE",
"number": string
}
ANY
Example:
Structure:
{
"type": "ANY"
}
UNKNOWN
Example:
Structure:
{
"type": "UNKNOWN"
}
PARENTHESIS
Example:
Structure:
{
"type": "PARENTHESIS",
"value": node
}
Others
We can use a parenthesis to change operator orders.
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.
License
This script is licensed under the MIT.