xiaohongshu
xiaohongshu
method-shorthand-jsdoc
Move helper functions into return objects using method shorthand for proper JSDoc preservation. Use when factory functions have internal helpers that should expose documentation to consumers, or when hovering over returned methods shows no JSDoc.
Full skill instructions
When factory functions have helper functions that are only used by returned methods, move them INTO the return object using method shorthand. This ensures JSDoc comments are properly passed through to consumers.
You write a factory function with a well-documented helper:
function createHeadDoc(options: { workspaceId: string }) {
const { workspaceId } = options;
/**
* Get the current epoch number.
*
* Computes the maximum of all client-proposed epochs.
* This ensures concurrent bumps converge to the same version.
*
* @returns The current epoch (0 if no bumps have occurred)
*/
function getEpoch(): number {
let max = 0;
for (const value of epochsMap.values()) {
max = Math.max(max, value);
}
return max;
}
return {
workspaceId,
getEpoch, // JSDoc is NOT visible when hovering on returned object!
bumpEpoch(): number {
const next = getEpoch() + 1; // Calling internal helper
return next;
},
};
}
When you hover over head.getEpoch() in your IDE, you see... nothing. The JSDoc is lost.
Move the helper INTO the return object using method shorthand:
function createHeadDoc(options: { workspaceId: string }) {
const { workspaceId } = options;
return {
workspaceId,
/**
* Get the current epoch number.
*
* Computes the maximum of all client-proposed epochs.
* This ensures concurrent bumps converge to the same version.
*
* @returns The current epoch (0 if no bumps have occurred)
*/
getEpoch(): number {
let max = 0;
for (const value of epochsMap.values()) {
max = Math.max(max, value);
}
return max;
},
bumpEpoch(): number {
const next = this.getEpoch() + 1; // Use this.methodName()
return next;
},
};
}
Now hovering over head.getEpoch() shows the full JSDoc.
function semantics - this is bound to the object, so this.getEpoch() works// BAD: Helper defined separately, JSDoc lost on return
function createService(client) {
/** Fetches user data with caching. */
function fetchUser(id: string) { ... }
return {
fetchUser, // JSDoc not visible to consumers!
getProfile(id: string) {
return fetchUser(id); // Works, but consumers can't see docs
},
};
}
// GOOD: Method shorthand, JSDoc preserved
function createService(client) {
return {
/** Fetches user data with caching. */
fetchUser(id: string) { ... },
getProfile(id: string) {
return this.fetchUser(id); // Use this.method()
},
};
}
Use this pattern when:
Keep helpers separate when:
Arrow functions don't have their own this:
// BAD: Arrow function, this is undefined
return {
getEpoch: () => { ... },
bumpEpoch: () => {
this.getEpoch(); // ERROR: this is undefined!
},
};
// GOOD: Method shorthand has correct this binding
return {
getEpoch() { ... },
bumpEpoch() {
this.getEpoch(); // Works!
},
};
From packages/epicenter/src/core/docs/head-doc.ts:
export function createHeadDoc(options: { workspaceId: string; ydoc?: Y.Doc }) {
const { workspaceId } = options;
const ydoc = options.ydoc ?? new Y.Doc({ guid: workspaceId });
const epochsMap = ydoc.getMap<number>('epochs');
return {
ydoc,
workspaceId,
/**
* Get the current epoch number.
*
* Computes the maximum of all client-proposed epochs.
* This ensures concurrent bumps converge to the same version
* without skipping epoch numbers.
*
* @returns The current epoch (0 if no bumps have occurred)
*/
getEpoch(): number {
let max = 0;
for (const value of epochsMap.values()) {
max = Math.max(max, value);
}
return max;
},
/**
* Bump the epoch to the next version.
*
* @returns The new epoch number after bumping
*/
bumpEpoch(): number {
const next = this.getEpoch() + 1;
epochsMap.set(ydoc.clientID.toString(), next);
return next;
},
// ... other methods using this.getEpoch()
};
}
| Approach | JSDoc Visible? | this Works? |
|---|---|---|
| Separate helper + reference | No | N/A |
| Arrow function in return | Yes | No |
| Method shorthand in return | Yes | Yes |
Method shorthand is the only approach that preserves JSDoc AND allows methods to call each other via this.
xiaohongshu
technical spec
product ux expert
database patterns
Conduct multi-agent task orchestration and workflow coordination.
Initialize project with Conductor artifacts (product definition,
Expert in web animations, transitions, and motion design using Framer Motion and CSS
Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...
PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.
Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...
Display project status, active tracks, and next actions
Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience