Skip to content

Handle TypeScript optional property syntax #76

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,22 @@ To:

Also removes trailing commas from object types.

### Optional properties

```js
/**
* @type {{a: number, b?: string}}
*/
```

To:

```js
/**
* @type {{a: number, b: string}}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you try if @type {{a: number, b: string=}} would work in JSDoc? It would be nice if we could keep the information that b is meant to be optional.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TS doesn't allow this syntax

Screenshot 2025-05-25 at 11 43 17

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant the translation to JSDoc, not the input type annotation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@type {{a: number, b: string=}} ends up as Object in the generated docs.

You'd have to define it as:

/**
 * @type {object}
 * @property {number} a
 * @property {string=} b
 */

To output docs for each property and whether or not they're optional

*/
```

### TS inline function syntax

```js
Expand Down
11 changes: 11 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,17 @@ exports.defineTags = function (dictionary) {
case '\\':
// Skip escaped character
++i;
break;
case '?':
// Remove optional property question marks
if (
!isWithinString &&
openCurly > 1 &&
/^\s*:/.test(tagText.slice(i + 1))
) {
replacements.push([i, i + 1, '']);
}

break;
case '"':
case "'":
Expand Down
144 changes: 120 additions & 24 deletions test/dest/expected.json
Original file line number Diff line number Diff line change
Expand Up @@ -742,14 +742,110 @@
"params": []
},
{
"comment": "/**\n * {@link module:test/sub/NumberStore~NumberStore NumberStore}\n */",
"comment": "/** @type {{ foo?: string; bar: string?, baz ? : string? }} */",
"meta": {
"range": [
1424,
1456
1456,
1521
],
"filename": "index.js",
"lineno": 65,
"columnno": 0,
"code": {
"name": "exports.optionalProperties",
"type": "VariableDeclaration"
}
},
"type": {
"names": [
"Object"
]
},
"name": "optionalProperties",
"longname": "module:test.optionalProperties",
"kind": "constant",
"memberof": "module:test",
"scope": "static"
},
{
"comment": "",
"meta": {
"range": [
1469,
1520
],
"filename": "index.js",
"lineno": 65,
"columnno": 13,
"code": {
"name": "optionalProperties",
"type": "ObjectExpression",
"value": "{\"foo\":\"bar\",\"bar\":null}"
}
},
"undocumented": true,
"name": "optionalProperties",
"longname": "module:test~optionalProperties",
"kind": "constant",
"scope": "inner",
"memberof": "module:test",
"params": []
},
{
"comment": "",
"meta": {
"range": [
1494,
1504
],
"filename": "index.js",
"lineno": 66,
"columnno": 2,
"code": {
"name": "foo",
"type": "Literal",
"value": "bar"
}
},
"undocumented": true,
"name": "foo",
"longname": "module:test~optionalProperties.foo",
"kind": "member",
"memberof": "module:test~optionalProperties",
"scope": "static"
},
{
"comment": "",
"meta": {
"range": [
1508,
1517
],
"filename": "index.js",
"lineno": 67,
"columnno": 2,
"code": {
"name": "bar",
"type": "Literal",
"value": null
}
},
"undocumented": true,
"name": "bar",
"longname": "module:test~optionalProperties.bar",
"kind": "member",
"memberof": "module:test~optionalProperties",
"scope": "static"
},
{
"comment": "/**\n * {@link module:test/sub/NumberStore~NumberStore NumberStore}\n */",
"meta": {
"range": [
1554,
1586
],
"filename": "index.js",
"lineno": 73,
"columnno": 0,
"code": {
"name": "exports.Link",
Expand All @@ -767,11 +863,11 @@
"comment": "",
"meta": {
"range": [
1437,
1455
1567,
1585
],
"filename": "index.js",
"lineno": 67,
"lineno": 73,
"columnno": 13,
"code": {
"name": "Link",
Expand All @@ -791,11 +887,11 @@
"comment": "/**\n * {@link module:test/sub/NumberStore~NumberStore Num}\n */",
"meta": {
"range": [
1493,
1533
1623,
1663
],
"filename": "index.js",
"lineno": 72,
"lineno": 78,
"columnno": 0,
"code": {
"name": "exports.LinkWithText",
Expand All @@ -813,11 +909,11 @@
"comment": "",
"meta": {
"range": [
1506,
1532
1636,
1662
],
"filename": "index.js",
"lineno": 72,
"lineno": 78,
"columnno": 13,
"code": {
"name": "LinkWithText",
Expand All @@ -837,11 +933,11 @@
"comment": "/**\n * {@link module:test/sub/NumberStore~NumberStore NumberStore.getNumber}\n */",
"meta": {
"range": [
1576,
1626
1706,
1756
],
"filename": "index.js",
"lineno": 77,
"lineno": 83,
"columnno": 0,
"code": {
"name": "exports.LinkWithMemberAccessor",
Expand All @@ -859,11 +955,11 @@
"comment": "",
"meta": {
"range": [
1589,
1625
1719,
1755
],
"filename": "index.js",
"lineno": 77,
"lineno": 83,
"columnno": 13,
"code": {
"name": "LinkWithMemberAccessor",
Expand All @@ -883,11 +979,11 @@
"comment": "/**\n * {@link module:test/sub/NumberStore~NumberStore Num}\n */",
"meta": {
"range": [
1673,
1730
1803,
1860
],
"filename": "index.js",
"lineno": 82,
"lineno": 88,
"columnno": 0,
"code": {
"name": "exports.LinkWithMemberAccessorAndText",
Expand All @@ -905,11 +1001,11 @@
"comment": "",
"meta": {
"range": [
1686,
1729
1816,
1859
],
"filename": "index.js",
"lineno": 82,
"lineno": 88,
"columnno": 13,
"code": {
"name": "LinkWithMemberAccessorAndText",
Expand Down
6 changes: 6 additions & 0 deletions test/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ export const bracketNotation = 1;
/** @type {[number, [number, string], "[number, boolean]"]} */
export const nesteedTuples = [1, [1, 'a'], '[number, boolean]'];

/** @type {{ foo?: string; bar: string?, baz ? : string? }} */
export const optionalProperties = {
foo: 'bar',
bar: null,
};

/**
* {@link NumberStore}
*/
Expand Down