1"use strict";(self.webpackChunkapi_extractor_com=self.webpackChunkapi_extractor_com||[]).push([[7630],{2940:(e,t,a)=>{a.r(t),a.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>u,frontMatter:()=>l,metadata:()=>p,toc:()=>m});var n=a(6443),r=a(8338),i=(a(829),a(5552)),o=["components"],l={title:"Doc comment syntax"},s=void 0,p={unversionedId:"pages/tsdoc/doc_comment_syntax",id:"pages/tsdoc/doc_comment_syntax",title:"Doc comment syntax",description:"API Extractor parses your TypeScript code comments to obtain documentation and additional type information.",source:"@site/docs/pages/tsdoc/doc_comment_syntax.md",sourceDirName:"pages/tsdoc",slug:"/pages/tsdoc/doc_comment_syntax",permalink:"/pages/tsdoc/doc_comment_syntax",draft:!1,editUrl:"https://github.com/microsoft/rushstack-websites/tree/main/websites/api-extractor.com/docs/pages/tsdoc/doc_comment_syntax.md",tags:[],version:"current",frontMatter:{title:"Doc comment syntax"},sidebar:"docsSidebar",previous:{title:"Getting Help",permalink:"/pages/setup/help"},next:{title:"Declaration references",permalink:"/pages/tsdoc/declaration_references"}},c={},m=[{value:"Which comments are parsed by API Extractor?",id:"which-comments-are-parsed-by-api-extractor",level:2},{value:"Comment structure",id:"comment-structure",level:2},{value:"Release tags",id:"release-tags",level:2},{value:"See also",id:"see-also",level:2}],d={toc:m},g="wrapper";function u(e){var t=e.components,a=(0,r.A)(e,o);return(0,i.yg)(g,(0,n.A)({},d,a,{components:t,mdxType:"MDXLayout"}),(0,i.yg)("head",null,(0,i.yg)("link",{rel:"canonical",href:"https://api-extractor.com/pages/pages/tsdoc/doc_comment_syntax/"})),(0,i.yg)("p",null,"API Extractor parses your TypeScript code comments to obtain documentation and additional type information.\nIt expects your code comments to use TSDoc format. We won't provide a full description of the grammar here;\ninstead, please refer to the ",(0,i.yg)("a",{parentName:"p",href:"https://github.com/microsoft/tsdoc"},"TSDoc project"),".) If you've used\nJSDoc for JavaScript source code, TSDoc will be very similar, but be aware that there are some syntax differences."),(0,i.yg)("p",null,"The TSDoc language can be extended by defining custom tags. API Extractor's particular dialect of TSDoc is\nreferred to as \"",(0,i.yg)("strong",{parentName:"p"},"AEDoc"),'". (Support for TSDoc was introduced with API Extractor 6.x. In earlier releases,\nAPI Extractor used a proprietary syntax that was also called as "AEDoc", but this is now obsolete.)'),(0,i.yg)("blockquote",null,(0,i.yg)("p",{parentName:"blockquote"},(0,i.yg)("strong",{parentName:"p"},"TSDoc Playground")),(0,i.yg)("p",{parentName:"blockquote"},"By the way, the ",(0,i.yg)("a",{parentName:"p",href:"https://microsoft.github.io/tsdoc/"},"TSDoc Playground")," website provides an\ninteractive way to experiment with code comments to see how they will be parsed. Give it a try!")),(0,i.yg)("h2",{id:"which-comments-are-parsed-by-api-extractor"},"Which comments are parsed by API Extractor?"),(0,i.yg)("p",null,"In order for API Extractor to parse a code comment, all of the following must be true:"),(0,i.yg)("ul",null,(0,i.yg)("li",{parentName:"ul"},"The comment must appear in the emitted .d.ts file for your class"),(0,i.yg)("li",{parentName:"ul"},"The comment must begin with the special ",(0,i.yg)("inlineCode",{parentName:"li"},"/**")," delimiter (two stars)"),(0,i.yg)("li",{parentName:"ul"},"The comment must appears immediately before an exported declaration; OR the comment appears at the top of the\nentry point file and contains a ",(0,i.yg)("inlineCode",{parentName:"li"},"@packageDocumentation")," tag")),(0,i.yg)("p",null,"Note that if a declaration has multiple comment blocks, only the closest one will be considered. For example:"),(0,i.yg)("pre",null,(0,i.yg)("code",{parentName:"pre",className:"language-ts"},"/**\n * Comment for f1.\n */\nexport function f1(): void {}\n\n/**\n * THIS COMMENT WILL BE IGNORED ENTIRELY.\n */\n\n/**\n * Comment for f2.\n */\nexport function f2(): void {}\n")),(0,i.yg)("h2",{id:"comment-structure"},"Comment structure"),(0,i.yg)("p",null,"The overall anatomy of a TSDoc comment has these components:"),(0,i.yg)("ul",null,(0,i.yg)("li",{parentName:"ul"},(0,i.yg)("strong",{parentName:"li"},"The summary section:"),' The documentation content up until the first block tag is called the "summary".\nThe summary section should be brief. On a documentation web site, it will be shown on a page that lists summaries\nfor many different API items. On a detail page for a single item, the summary will be shown followed by the\nremarks section (if any).'),(0,i.yg)("li",{parentName:"ul"},(0,i.yg)("strong",{parentName:"li"},"The remarks block:"),' The "remarks" block starts with the ',(0,i.yg)("inlineCode",{parentName:"li"},"@remarks")," block tag. Unlike the summary, the remarks\nmay contain lengthy documentation content. The remarks section should not restate information from the summary,\nsince the summary section will always be displayed wherever the remarks section appears."),(0,i.yg)("li",{parentName:"ul"},(0,i.yg)("strong",{parentName:"li"},"Additional blocks:")," Other TSDoc blocks typically follow the ",(0,i.yg)("inlineCode",{parentName:"li"}
1,"@remarks")," block. Each block is introduced\nby a block tag such as ",(0,i.yg)("inlineCode",{parentName:"li"},"@param"),", ",(0,i.yg)("inlineCode",{parentName:"li"},"@returns"),", ",(0,i.yg)("inlineCode",{parentName:"li"},"@example"),", etc."),(0,i.yg)("li",{parentName:"ul"},(0,i.yg)("strong",{parentName:"li"},"Modifier tags:")," The modifier tags typically come last. Modifier tags don't have an associated block of content;\ninstead, their presence indicates an aspect of the declaration. Some examples of modifier tags are: ",(0,i.yg)("inlineCode",{parentName:"li"},"@public"),",\n",(0,i.yg)("inlineCode",{parentName:"li"},"@beta"),", and ",(0,i.yg)("inlineCode",{parentName:"li"},"@virtual"),"."),(0,i.yg)("li",{parentName:"ul"},(0,i.yg)("strong",{parentName:"li"},"Inline tags:")," Inline tags can appear inside any section, and are always delimited by ",(0,i.yg)("inlineCode",{parentName:"li"},"{")," and ",(0,i.yg)("inlineCode",{parentName:"li"},"}")," characters.\nAdditional content can appear after the tag name and before the ",(0,i.yg)("inlineCode",{parentName:"li"},"}")," delimiter. Its format is tag-specific.\nExamples of inline tags are ",(0,i.yg)("inlineCode",{parentName:"li"},"{@link}")," and ",(0,i.yg)("inlineCode",{parentName:"li"},"{@inheritDoc}"),".")),(0,i.yg)("p",null,"Here's some sample code that illustrates all the various components of the doc comment syntax:"),(0,i.yg)("pre",null,(0,i.yg)("code",{parentName:"pre",className:"language-ts"},"/**\n * The base class for all widgets.\n *\n * @remarks\n * For details, see {@link https://example.com/my-protocol | the protocol spec}.\n *\n * @public\n */\nexport abstract class BaseWidget {\n /**\n * Draws the widget.\n * @remarks\n *\n * The `draw` member implements the main rendering for a widget.\n *\n * @param force - whether to force redrawing\n * @returns true, if rendering occurred; false, if the view was already up to date\n *\n * @beta @virtual\n */\n public draw(force: boolean): boolean {\n . . .\n }\n\n /**\n * Whether the widget is currently visible.\n *\n * @example\n * Here's some example code to hide a widget:\n *\n * ```ts\n * let myWidget = new MyWidget();\n * myWidget.visible = false;\n * ```\n *\n * @defaultValue `true`\n */\n public visible: boolean = true;\n\n /**\n * Gets or set the title of this widget\n */\n public get title(): string {\n . . .\n }\n\n // NOTE: API Extractor considers your property getter and setter functions to be\n // a single API item. Don't write any documentation for the setter.\n public set title(value: string) {\n . . .\n }\n}\n")),(0,i.yg)("h2",{id:"release-tags"},"Release tags"),(0,i.yg)("p",null,"The four release tags are: ",(0,i.yg)("inlineCode",{parentName:"p"},"@internal"),", ",(0,i.yg)("inlineCode",{parentName:"p"},"@alpha"),", ",(0,i.yg)("inlineCode",{parentName:"p"},"@beta"),", ",(0,i.yg)("inlineCode",{parentName:"p"},"@public"),". They are applied to API items such as\nclasses, member functions, enums, etc. API Extractor classifies each exported API item individually, according\nto its intended level of support:"),(0,i.yg)("ul",null,(0,i.yg)("li",{parentName:"ul"},(0,i.yg)("p",{parentName:"li"},(0,i.yg)("strong",{parentName:"p"},"internal"),': Indicates that an API item is meant only for usage by other NPM packages from the same maintainer.\nThird parties should never use "internal" APIs. To emphasize this, underscore prefixes should be used for items\nwith an (explicit) ',(0,i.yg)("inlineCode",{parentName:"p"},"@internal")," tag.")),(0,i.yg)("li",{parentName:"ul"},(0,i.yg)("p",{parentName:"li"},(0,i.yg)("strong",{parentName:"p"},"alpha"),': Indicates that an API item is eventually intended to be public, but currently is in an early stage\nof development. Third parties should not use "alpha" APIs.')),(0,i.yg)("li",{parentName:"ul"},(0,i.yg)("p",{parentName:"li"},(0,i.yg)("strong",{parentName:"p"},"beta"),': Indicates that an API item has been released as a preview or for experimental purposes. Third parties\nare encouraged to try it and provide feedback. However, a "beta" API should NOT be used in production, because\nit may be changed or removed in a future version.')),(0,i.yg)("li",{parentName:"ul"},(0,i.yg)("p",{parentName:"li"},(0,i.yg)("strong",{parentName:"p"},"public"),": Indicates that an API item has been officially released, and is now part of the supported contract\nfor a package. If the ",(0,i.yg)("a",{parentName:"p",href:"https://semver.org/"},"SemVer")," versioning scheme is used, then the API signature cannot\nbe changed without a MAJOR version increment."))),(0,i.yg)("blockquote",null,(0,i.yg)("p",{parentName:"blockquote"},"NOTE: TypeScript's ",(0,i.yg)("inlineCode",{parentName:"p"},"public"),"/",(0,i.yg)("inlineCode",{parentName:"p"},"protected"),"/",(0,i.yg)("inlineCode",{parentName:"p"},"private")," keywords are unrelated to the AEDoc release tags.\nFor example, a member function will typically have the ",(0,i.yg)("inlineCode",{parentName:"p"},"public")," TypeScript keyword regardless of whether\nit is classified as ",(0,i.yg)("inlineCode",{parentName:"p"},"@public")," or ",(0,i.yg)("inlineCode",{parentName:"p"},"@internal")," in the doc comment.")),(0,i.yg)("p",null,"When an API is first introduced, it typically starts as ",(0,i.yg)("strong",{parentName:"p"},"alpha"),". As the design matures, it graduates\nfrom ",(0,i.yg)("strong",{parentName:"p"},"alpha")," --\x3e ",(0,i.yg)("strong",{parentName:"p"},"beta")," --\x3e ",(0,i.yg)("strong",{parentName:"p"},"public"),". The ",(0,i.yg)("strong",{parentName:"p"},"internal")," designation is mostly used to solve plumbing problems,\nand usually isn't on any road map to becoming public. (There is also a ",(0,i.yg)("inlineCode",{parentName:"p"},"@deprecated")," tag, but it is an option\nthat can be combined with any of the above tags.)"),(0,i.yg)("p",null,"The release tag applies recursively to members of a container (e.g. class or interface). For example, if a class\nis marked as ",(0,i.yg)("inlineCode",{parentName:"p"},"@beta"),", then all of its members automatically have this status; you DON'T need add the ",(0,i.yg)("inlineCode",{parentName:"p"},"@beta")," tag to\neach member function. However, you could add ",(0,i.yg)("inlineCode",{parentName:"p"},"@internal")," to a member function to give it a different release status."),(0,i.yg)("blockquote",null,(0,i.yg)("p",{parentName:"blockquote"},"NOTE: If a container (e.g. a class or interface) has an ",(0,i.yg)("inlineCode",{parentName:"p"},"@internal")," tag, then an underscore prefix should be added\nto its name, but its members do NOT need underscores. Whereas e.g. if ",(0,i.yg)("inlineCode",{parentName:"p"},"@internal")," is applied to a member function\nof a ",(0,i.yg)("inlineCode",{parentName:"p"},"@beta")," class, then the internal function SHOULD have an underscore prefix.")),(0,i.yg)("p",null,"Lastly, note that certain logical rules apply. For example, a ",(0,i.yg)("inlineCode",{parentName:"p"},"@public")," function should not return a ",(0,i.yg)("inlineCode",{parentName:"p"},"@beta")," type.\nA ",(0,i.yg)("inlineCode",{parentName:"p"},"@beta")," class should not inherit from an ",(0,i.yg)("inlineCode",{parentName:"p"},"@internal")," base class. etc. API Extractor does not currently validate\nthese rules, but it will soon."),(0,i.yg)("h2",{id:"see-also"},"See also"),(0,i.yg)("ul",null,(0,i.yg)("li",{parentName:"ul"},(0,i.yg)("a",{parentName:"li",href:"/pages/tsdoc/tag_internal"},"@internal tag")),(0,i.yg)("li",{parentName:"ul"}
1,(0,i.yg)("a",{parentName:"li",href:"/pages/tsdoc/tag_alpha"},"@alpha tag")),(0,i.yg)("li",{parentName:"ul"},(0,i.yg)("a",{parentName:"li",href:"/pages/tsdoc/tag_beta"},"@beta tag")),(0,i.yg)("li",{parentName:"ul"},(0,i.yg)("a",{parentName:"li",href:"/pages/tsdoc/tag_public"},"@public tag")),(0,i.yg)("li",{parentName:"ul"},(0,i.yg)("a",{parentName:"li",href:"/pages/messages/ae-different-release-tags"},"ae-different-release-tags")),(0,i.yg)("li",{parentName:"ul"},(0,i.yg)("a",{parentName:"li",href:"/pages/messages/ae-extra-release-tag"},"ae-extra-release-tag")),(0,i.yg)("li",{parentName:"ul"},(0,i.yg)("a",{parentName:"li",href:"/pages/messages/ae-incompatible-release-tags"},"ae-incompatible-release-tags")),(0,i.yg)("li",{parentName:"ul"},(0,i.yg)("a",{parentName:"li",href:"/pages/messages/ae-internal-missing-underscore"},"ae-internal-missing-underscore")),(0,i.yg)("li",{parentName:"ul"},(0,i.yg)("a",{parentName:"li",href:"/pages/messages/ae-internal-mixed-release-tag"},"ae-internal-mixed-release-tag"))))}u.isMDXComponent=!0},5552:(e,t,a)=>{a.d(t,{xA:()=>c,yg:()=>u});var n=a(829);function r(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function i(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),a.push.apply(a,n)}return a}function o(e){for(var t=1;t<arguments.length;t++){var a=null!=arguments[t]?arguments[t]:{};t%2?i(Object(a),!0).forEach(function(t){r(e,t,a[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(a)):i(Object(a)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(a,t))})}return e}function l(e,t){if(null==e)return{};var a,n,r=function(e,t){if(null==e)return{};var a,n,r={},i=Object.keys(e);for(n=0;n<i.length;n++)a=i[n],t.indexOf(a)>=0||(r[a]=e[a]);return r}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n<i.length;n++)a=i[n],t.indexOf(a)>=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(r[a]=e[a])}return r}var s=n.createContext({}),p=function(e){var t=n.useContext(s),a=t;return e&&(a="function"==typeof e?e(t):o(o({},t),e)),a},c=function(e){var t=p(e.components);return n.createElement(s.Provider,{value:t},e.children)},m="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},g=n.forwardRef(function(e,t){var a=e.components,r=e.mdxType,i=e.originalType,s=e.parentName,c=l(e,["components","mdxType","originalType","parentName"]),m=p(a),g=r,u=m["".concat(s,".").concat(g)]||m[g]||d[g]||i;return a?n.createElement(u,o(o({ref:t},c),{},{components:a})):n.createElement(u,o({ref:t},c))});function u(e,t){var a=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var i=a.length,o=new Array(i);o[0]=g;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l[m]="string"==typeof e?e:r,o[1]=l;for(var p=2;p<i;p++)o[p]=a[p];return n.createElement.apply(null,o)}return n.createElement.apply(null,a)}g.displayName="MDXCreateElement"}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.