TypeScript comments are JavaScript comments: // for the rest of a line and /* */ for a block. A block comment starting with /** is a documentation comment (JSDoc), which editors display when you hover over the thing it documents. On top of that, TypeScript reads a few special comments that change how the compiler checks your code.
Output:
212
Comments do not affect the program. They also do not affect type checking, except for the directive comments covered below.
Single-Line and Block Comments
// comments out everything after it on the line, which is also the quick way to disable a line of code. /* */ can sit in the middle of a line or cover many lines.
Block comments do not nest. The first */ ends the comment, so wrapping code that already contains a block comment breaks:
/* outer comment /* inner comment */ this text is now code */
The compiler then tries to read this text is now code */ as code and reports a syntax error. To comment out a region that contains block comments, use // on each line; most editors do it with Ctrl+/ (Cmd+/ on macOS).
JSDoc Documentation Comments
A /** ... */ comment directly before a function, class, method, property, interface or variable documents it. Editors show its text in the hover tooltip and in autocompletion, and documentation generators such as TypeDoc turn it into reference pages. TSDoc, a standard for these comments in TypeScript code started by Microsoft, uses the same syntax for the common tags:
| Tag | Meaning |
|---|---|
@param name description | Describes a parameter |
@returns description | Describes the return value |
@throws description | Describes an error the function can throw |
@example | Starts an example block, usually followed by a code fence |
@deprecated reason | Marks an API as deprecated; editors draw it |
@see or {@link Name} | Points to related code |
@remarks | Longer explanation after the summary line |
In a .ts file, do not repeat the types in JSDoc. The annotations in the code are the types, and JSDoc type tags are ignored there: /** @type {string} */ const v: number = 5; compiles without complaint because only : number counts.
In an editor, hovering over transfer or balance anywhere in the project shows these descriptions.
Marking Code as Deprecated
@deprecated does not cause a compile error. It tells editors to show every use of the deprecated function with a strikethrough and the reason on hover, which is the gentle way to steer callers to a replacement:
Output:
$19.99
19.99 EUR
@ts-expect-error and @ts-ignore
These two comments silence type errors on the line that follows. Sometimes that is the right call: a test that checks how a function handles bad input at runtime, or a known gap in a library's types.
Output:
runtime error: text.toUpperCase is not a function
Without the comment, shout(42) is a compile error (TS2345). With it, the file compiles and the call reaches the runtime, which is the point of this test.
The difference between the two directives shows up when the error goes away. @ts-expect-error insists there is an error to suppress, so a stale comment becomes an error itself:
index.ts(6,1): error TS2578: Unused '@ts-expect-error' directive.
// @ts-ignore in the same place stays silent, both while the error exists and after it is gone. That is why @ts-expect-error is the better default: when someone fixes the types, the compiler tells you the suppression can go. Always add a reason after the directive, as in the example above, so the next reader knows why it is there.
Both only cover the next line and all errors on it. For whole-value escapes, an explicit as unknown as T or a runtime check is usually clearer than a suppression comment.
@ts-nocheck and @ts-check
// @ts-nocheck at the top of a file turns off type checking for that whole file. It has to come first, before any code: placed further down, it is ignored and the errors still appear.
// @ts-nocheck
const n: number = "not a number"; // no error reported
It is useful while migrating a large JavaScript codebase, and a smell anywhere else.
// @ts-check does the opposite in a JavaScript file: it turns on type checking for that .js file, using inference and JSDoc types, even when checkJs is off in tsconfig.json (the file still has to be part of the project, through allowJs):
// @ts-check
/**
* @param {number} cents
* @returns {string}
*/
function formatCents(cents) {
return (cents / 100).toFixed(2);
}
formatCents("12"); // error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.
In JavaScript files the JSDoc tags are the types, which is how many projects get type checking without converting files to .ts.
Triple-Slash Directives
A comment of the form /// <reference ... /> at the very top of a file is a compiler directive:
/// <reference types="node" />
/// <reference lib="es2023.array" />
/// <reference path="./globals.d.ts" />
types="node"adds a@typespackage to the program, like listing it in"types"intsconfig.json.lib="..."adds a built-in library to the program, like theliboption.path="..."includes another file, mostly used inside.d.tsfiles.
In application code, import statements and tsconfig.json settings replace almost every use; you mostly meet these directives in declaration files and generated code such as Vite's vite-env.d.ts. As a quick demonstration, lib makes a newer array method available in this file:
Comments in the Compiled Output
tsc keeps comments in the JavaScript it writes. Set "removeComments": true to drop them; comments starting with /*! survive even then, which is the convention for license headers:
/*! MyLib v1.2.0 | MIT License */
JSDoc comments are also copied into .d.ts files when declaration is on, so users of a library see the descriptions in their editor.
Frequently Asked Questions
How do you write a comment in TypeScript?
The same way as in JavaScript: // starts a comment that runs to the end of the line, and /* ... */ wraps a comment that can span several lines. A block comment that starts with /** is a documentation (JSDoc) comment, which editors show when you hover over the documented function, class or property.
What is the difference between @ts-ignore and @ts-expect-error?
Both silence the type errors on the next line. // @ts-expect-error also checks that there is an error there: if the line stops having one, the compiler reports error TS2578: Unused '@ts-expect-error' directive., so stale suppressions get noticed. // @ts-ignore stays silent forever. Prefer @ts-expect-error.
How do I ignore TypeScript errors in a whole file?
Put // @ts-nocheck at the top of the file, before any code. The compiler then reports no type errors for that file (syntax errors still appear). It is a migration tool; for a single line use // @ts-expect-error instead.
Do comments end up in the compiled JavaScript?
Yes, by default tsc keeps comments in the output. With "removeComments": true it drops them, except comments that start with /*!, which are kept for license headers. Bundlers and minifiers usually strip them in production builds.
Should I write types in JSDoc comments in a .ts file?
No. In .ts files, JSDoc type tags such as @type {string} or @param {number} x are ignored for type checking; the annotations in the code are the types. Use JSDoc in .ts files for descriptions, and JSDoc types only in .js files checked with // @ts-check or checkJs.