diff --git a/README.md b/README.md index ad31eae..d66e1d1 100644 --- a/README.md +++ b/README.md @@ -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}} + */ +``` + ### TS inline function syntax ```js diff --git a/index.js b/index.js index 416eb4d..24401a8 100644 --- a/index.js +++ b/index.js @@ -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 "'": diff --git a/test/dest/expected.json b/test/dest/expected.json index f17fd3a..6261209 100644 --- a/test/dest/expected.json +++ b/test/dest/expected.json @@ -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", @@ -767,11 +863,11 @@ "comment": "", "meta": { "range": [ - 1437, - 1455 + 1567, + 1585 ], "filename": "index.js", - "lineno": 67, + "lineno": 73, "columnno": 13, "code": { "name": "Link", @@ -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", @@ -813,11 +909,11 @@ "comment": "", "meta": { "range": [ - 1506, - 1532 + 1636, + 1662 ], "filename": "index.js", - "lineno": 72, + "lineno": 78, "columnno": 13, "code": { "name": "LinkWithText", @@ -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", @@ -859,11 +955,11 @@ "comment": "", "meta": { "range": [ - 1589, - 1625 + 1719, + 1755 ], "filename": "index.js", - "lineno": 77, + "lineno": 83, "columnno": 13, "code": { "name": "LinkWithMemberAccessor", @@ -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", @@ -905,11 +1001,11 @@ "comment": "", "meta": { "range": [ - 1686, - 1729 + 1816, + 1859 ], "filename": "index.js", - "lineno": 82, + "lineno": 88, "columnno": 13, "code": { "name": "LinkWithMemberAccessorAndText", diff --git a/test/src/index.js b/test/src/index.js index 17307f3..65f9114 100644 --- a/test/src/index.js +++ b/test/src/index.js @@ -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} */