JSDoc & Docstrings
6 exercises — write and review JSDoc comment blocks: @param, @returns, @throws, @deprecated, @example.
• Summary line: "Converts a string to a URL-safe slug." — one sentence, imperative mood
• @param: type + name + description ("The input string to slugify")
• @returns: type + description ("The lowercased, hyphen-separated slug")
• @example: shows concrete input → output behavior
JSDoc style conventions:
• Use imperative mood for the summary: "Converts...", "Validates...", "Returns..." — not "This function converts..."
• Keep the summary to one sentence ending with a period
• Describe what the parameter IS, not what the code does with it
• @returns should describe the return value meaning, not just the type
• @example is optional but extremely valuable for non-obvious functions
Tools that parse JSDoc: VS Code IntelliSense, TypeDoc, JSDoc HTML generator.
The @throws tag format:
@throws {"{ErrorType}"} Description of when it throws.Rules:
• The error type in curly braces:
{"{TypeError}"}, {"{RangeError}"}, {"{Error}"}, or a custom error class• The description starts with "When" or "If": "When the token has expired", "If the user does not exist"
Multiple @throws:
* @throws {ValidationError} When required fields are missing.
* @throws {AuthError} When the JWT signature is invalid.
* @throws {RateLimitError} When more than 100 requests per minute.Why document throws:
• Callers need to know what exceptions to catch
• In TypeScript, exceptions are not part of the type system (unlike Java's checked exceptions)
• Without documentation, a caller may not wrap the call in try/catch and the error propagates silently to the top level
• Square brackets around the name:
[timeout] = optional• Default value after equals:
[timeout=5000] = optional, defaults to 5000• Description should mention the unit: "milliseconds", "seconds", "bytes"
• Include "Defaults to X" in the description for clarity
JSDoc parameter documentation patterns:
@param {string} name // required, no default
@param {string} [name] // optional, no default (can be undefined)
@param {string} [name="anonymous"] // optional, defaults to "anonymous"
@param {Object} options // required object
@param {string} options.host // property of options
@param {number} [options.port=80] // optional property with defaultThe options object pattern is particularly useful for functions with many configurable parameters.
Best practice — include WHY and WHAT to use instead:
/**
* @deprecated Since v2.3.0. Use {@link fetchUserById} instead.
* Will be removed in v3.0.0.
*/
function getUser(id: string) { ... }Good @deprecated annotation includes:
1. Since version — when it was deprecated
2. Replacement —
{"{@link newFunctionName}"} — creates a clickable link in IDEs3. Removal version (if known) — when it will be removed
IDE behaviour: VS Code shows deprecated symbols with a strikethrough in autocomplete and usages. TypeScript compiler can issue warnings for deprecated usage with the
@deprecated JSDoc tag even without strict mode.Communication in English: "deprecated" ≠ "deleted". Deprecated = "we recommend you stop using this". Deleted = "this no longer exists".
• The type is
{"{Promise}"} where T is the resolved value's type• Describe BOTH the resolved value AND potential rejection causes
Examples:
@returns {Promise<void>} Resolves when the email is sent.
@returns {Promise<string>} Resolves with the generated token.
@returns {Promise<User[]>} Resolves with an array of matching users.
@returns {Promise<User|null>} Resolves with the user, or null if not found.Also document rejections:
* @returns {Promise<User>} Resolves with the authenticated user.
* @throws {AuthError} If the token is expired or invalid.
* @throws {NetworkError} If the identity provider is unreachable.Note: In TypeScript with strict mode, the return type annotation in the function signature is often sufficient. JSDoc is most valuable in .js files without TypeScript types, or for public API documentation.
Problems:
1.
{"{Error}"} — the base Error class; should name the specific error type2. "when there is an error" — circular; every @throws tag is about an error
3. No condition — what triggers the throw? What input? What state?
Improved version:
@throws {"{NotFoundError}"} When no user with the given ID exists in the database.Or:
@throws {"{TypeError}"} When userId is not a valid UUID string.Evaluating options A, B, D:
• Option A ✓ — type + name + meaningful description
• Option B ✓ — type + both possible values explained ("true if… false otherwise")
• Option D ✓ — @example with realistic input and expected return
The standard for @throws: specific error type + specific triggering condition. If you can't write a specific condition, the function probably needs clearer error handling design.
function getOrderDetails(orderId) {
const order = database.getOrder(orderId);
if (!order) {
return null;
}
return {
id: order.id,
totalAmount: order.totalAmount,
items: order.items
};
}
// @description This function calculates the average score.
function calculateAverageScore(scores: number[]): number {
if (scores.length === 0) {
return 0;
}
const sum = scores.reduce((acc, score) => acc + score, 0);
return sum / scores.length;
During a code review, Sarah comments: 'I'm not sure I fully understand what this function does. Could you add more detail about the input parameters and what it returns?' Which JSDoc comment would best address Sarah's concern?scores (an array of numbers representing scores), and the *type and meaning* of the return value (a number representing the calculated average). Sarah's comment highlights the need for more descriptive documentation – a key aspect of good code review practice.function getOrderDetails(orderId) {
const order = database.getOrder(orderId);
if (!order) {
return null;
}
return {
id: order.id,
totalAmount: order.totalAmount,
items: order.items
};
}function getOrderDetails(orderId) { const order = database.getOrder(orderId); if (!order) { return null;} return {
id: order.id,
totalAmount: order.totalAmount,
items: order.items
}; }function getOrderDetails(orderId) {
const order = database.getOrder(orderId);
if (!order) {
return null;
}
return {
id: order.id,
totalAmount: order.totalAmount,
items: order.items
};
}
// @description This function calculates the average score.
function calculateAverageScore(scores: number[]): number {
if (scores.length === 0) {
return 0;
}
const sum = scores.reduce((acc, score) => acc + score, 0);
return sum / scores.length;
During a code review, Sarah comments: 'I'm not sure I fully understand what this function does. Could you add more detail about the input parameters and what it returns?' Which JSDoc comment would best address Sarah's concern?scores (an array of numbers representing scores), and the *type and meaning* of the return value (a number representing the calculated average). Sarah's comment highlights the need for more descriptive documentation – a key aspect of good code review practice.function getOrderDetails(orderId) {
const order = database.getOrder(orderId);
if (!order) {
return null;
}
return {
id: order.id,
totalAmount: order.totalAmount,
items: order.items
};
}function getOrderDetails(orderId) { const order = database.getOrder(orderId); if (!order) { return null;} return {
id: order.id,
totalAmount: order.totalAmount,
items: order.items
}; }function getOrderDetails(orderId) {
const order = database.getOrder(orderId);
if (!order) {
return null;
}
return {
id: order.id,
totalAmount: order.totalAmount,
items: order.items
};
}
// @description This function calculates the average score.
function calculateAverageScore(scores: number[]): number {
if (scores.length === 0) {
return 0;
}
const sum = scores.reduce((acc, score) => acc + score, 0);
return sum / scores.length;
During a code review, Sarah comments: 'I'm not sure I fully understand what this function does. Could you add more detail about the input parameters and what it returns?' Which JSDoc comment would best address Sarah's concern?scores (an array of numbers representing scores), and the *type and meaning* of the return value (a number representing the calculated average). Sarah's comment highlights the need for more descriptive documentation – a key aspect of good code review practice.function getOrderDetails(orderId) {
const order = database.getOrder(orderId);
if (!order) {
return null;
}
return {
id: order.id,
totalAmount: order.totalAmount,
items: order.items
};
}function getOrderDetails(orderId) { const order = database.getOrder(orderId); if (!order) { return null;} return {
id: order.id,
totalAmount: order.totalAmount,
items: order.items
}; }function getOrderDetails(orderId) {
const order = database.getOrder(orderId);
if (!order) {
return null;
}
return {
id: order.id,
totalAmount: order.totalAmount,
items: order.items
};
}
// @description This function calculates the average score.
function calculateAverageScore(scores: number[]): number {
if (scores.length === 0) {
return 0;
}
const sum = scores.reduce((acc, score) => acc + score, 0);
return sum / scores.length;
During a code review, Sarah comments: 'I'm not sure I fully understand what this function does. Could you add more detail about the input parameters and what it returns?' Which JSDoc comment would best address Sarah's concern?scores (an array of numbers representing scores), and the *type and meaning* of the return value (a number representing the calculated average). Sarah's comment highlights the need for more descriptive documentation – a key aspect of good code review practice.function getOrderDetails(orderId) {
const order = database.getOrder(orderId);
if (!order) {
return null;
}
return {
id: order.id,
totalAmount: order.totalAmount,
items: order.items
};
}function getOrderDetails(orderId) { const order = database.getOrder(orderId); if (!order) { return null;} return {
id: order.id,
totalAmount: order.totalAmount,
items: order.items
}; }Option 1 correctly describes the function's purpose – retrieving data by ID. It also includes a helpful caveat about assuming a valid ID exists, which is crucial for documentation. Options B and C are too specific (mentioning name/address) and don't clearly state the primary input. Option D is incomplete and doesn't provide any JSDoc information.
The `@throws` tag is the correct choice because it specifically documents potential errors that the function might raise. It's vital to indicate what exceptions or errors are likely to occur and how they should be handled. Options B and C describe parameters and purpose respectively; neither addresses error handling directly. Option D is simply a description, lacking any critical information.
Option 1 directly explains the *reason* behind the changes – adding JSDoc comments. This provides context to reviewers and highlights the benefit of the modification. The other options focus on different aspects (bug fixes, refactoring, new features) which are not relevant to this commit's purpose.
The `@param` tag with a data type and range constraints (min/max) is the most appropriate choice. This clearly defines the expected input – a number between 0 and 100 representing the discount percentage. Options B provides only a description; C incorrectly specifies the parameter's type, while D leaves the documentation incomplete.
Option 2 accurately describes the function's purpose – it checks the format of an email address. It also correctly identifies the parameter and return value. Options A and B are incomplete; they only describe parameters or return values respectively without explaining *what* is being validated.
Frequently Asked Questions
What will I practice in "JSDoc & Docstrings — Code Comments Exercises"?
This is a Code Comments exercise set. It walks through 27 scenario-based multiple-choice questions built around real usage of Code Comments terminology that IT professionals encounter on the job.
Is this exercise free to use?
Yes. Every exercise on CoderSlingo, including this one, is free to complete with no account, sign-up, or paywall.
How many questions are in this exercise?
This set contains 27 questions. Each one shows immediate feedback and a detailed explanation after you answer, so you learn the correct usage right away rather than waiting for a final score.
Do I need prior experience to complete this exercise?
No prior experience is required. Each question includes a full explanation covering the reasoning behind the correct answer, so the exercise itself teaches the Code Comments vocabulary as you go.
Can I retry the exercise if I get questions wrong?
Yes — use the "Try again" button on the results screen to reset your answers and go through all the questions again. There is no limit on attempts.
Is my progress saved?
Your answers and score for the current session are tracked in the browser as you go. No account or login is needed, and there is nothing to install.
What if I don't understand a term used in a question?
Read the explanation shown after you answer each question — it breaks down the correct term in plain English with a real-world example. You can also check the site Glossary for quick definitions.
How is this different from reading a blog article on the topic?
Exercises like this one are interactive drills that test and reinforce specific vocabulary through multiple-choice questions, while blog articles explain concepts in prose. Practising here after reading builds active recall, not just passive recognition.
Where can I find more Code Comments exercises?
See the Code Comments exercises hub for the full set of related pages, or browse all exercise categories from the main Exercises index.
Can I use this exercise to prepare for a technical interview?
Yes — Code Comments vocabulary comes up often in technical discussions and interviews. Pair this exercise with our dedicated Interview Preparation section for role-specific practice.