@protected on a class member allows it inside the class and inside every subclass, and nowhere else. Since TypeScript 3.8, a use from outside is an error (TS2445, "Property 'rows' is protected and only accessible within class 'Report' and its subclasses"). It is the JavaScript spelling of TypeScript's protected modifier.
Use it for the parts of a base class that subclasses build on, such as shared state or helper methods, but that callers should not touch.
At a glance
| Use | JSDoc in a .js file | TypeScript in a .ts file |
|---|---|---|
| A protected member | /** @protected */
rows = []; | protected rows: string[] = []; |
Examples
export class Report {
/** @protected */
rows = /** @type {string[]} */ ([]);
/** @param {string} row */
add(row) {
this.rows.push(row);
}
}
export class CsvReport extends Report {
toCsv() {
return this.rows.join("\n");
}
}
const report = new CsvReport();
report.add("TEE-01,2");
report.rows.length;error TS2445: Property 'rows' is protected and only accessible within class 'Report' and its subclasses.export class Report {
protected rows: string[] = [];
add(row: string) {
this.rows.push(row);
}
}
export class CsvReport extends Report {
toCsv() {
return this.rows.join("\n");
}
}
const report = new CsvReport();
report.add("TEE-01,2");
report.rows.length;error TS2445: Property 'rows' is protected and only accessible within class 'Report' and its subclasses.jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} export class Exporter {
/**
* @protected
* @param {string} value
*/
quote(value) {
return `"${value.replaceAll('"', '""')}"`;
}
}
export class CsvExporter extends Exporter {
/** @param {string[]} cells */
row(cells) {
return cells.map((cell) => this.quote(cell)).join(",");
}
}
new CsvExporter().row(["TEE-01", "Cotton tee, large"]);export class Exporter {
protected quote(value: string) {
return `"${value.replaceAll('"', '""')}"`;
}
}
export class CsvExporter extends Exporter {
row(cells: string[]) {
return cells.map((cell) => this.quote(cell)).join(",");
}
}
new CsvExporter().row(["TEE-01", "Cotton tee, large"]);jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} What it allows
Inside CsvReport, this.rows is fine because CsvReport extends Report. From outside, report.rows fails even though report is a CsvReport. The second example shows a protected helper method that a subclass calls, which is the common case.
Gotchas
- Like
@private, the tag is a compile-time check; the property is ordinary at run time. - The accessibility tags do not work in constructor functions (see
@private); use aclass. - The
protectedkeyword is TypeScript syntax and an error in a.jsfile (TS8009).
Questions
Can a subclass make a @protected member public?
Yes, as in TypeScript: redeclare it in the subclass without the tag (or with @public), and it is public on the subclass.
Sources
- TypeScript 3.8: JSDoc property modifiers · TypeScript release notes
- JSDoc Reference: property modifiers · TypeScript handbook
- @protected · JSDoc
Last reviewed 20 October 2026.