@implements {Store} above a class asks TypeScript to check that the class provides every member of Store with compatible types. A missing or mistyped member is an error on the class (TS2420), exactly as with implements in a .ts file.
The type usually comes from a @typedef with an object type, an interface in a .d.ts file, or another class. The tag adds a check; it does not change the class's own type or add anything at run time.
At a glance
| Use | JSDoc in a .js file | TypeScript in a .ts file |
|---|---|---|
| A class that implements a type | /** @implements {Store} */
class MemoryStore { … } | class MemoryStore implements Store { … } |
Examples
/**
* @typedef {object} Store
* @property {(key: string) => Promise<string | undefined>} get
* @property {(key: string, value: string) => Promise<void>} set
*/
/** @implements {Store} */
export class MemoryStore {
/** @type {Map<string, string>} */
#data = new Map();
/** @param {string} key */
async get(key) {
return this.#data.get(key);
}
/**
* @param {string} key
* @param {string} value
*/
async set(key, value) {
this.#data.set(key, value);
}
}interface Store {
get(key: string): Promise<string | undefined>;
set(key: string, value: string): Promise<void>;
}
export class MemoryStore implements Store {
#data = new Map<string, string>();
async get(key: string) {
return this.#data.get(key);
}
async set(key: string, value: string) {
this.#data.set(key, value);
}
}jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} /**
* @typedef {object} Store
* @property {(key: string) => Promise<string | undefined>} get
* @property {(key: string, value: string) => Promise<void>} set
*/
/** @implements {Store} */
export class MemoryStore {error TS2420: Class 'MemoryStore' incorrectly implements interface 'Store'.
Property 'set' is missing in type 'MemoryStore' but required in type 'Store'.
/** @type {Map<string, string>} */
#data = new Map();
/** @param {string} key */
async get(key) {
return this.#data.get(key);
}
}jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} Where the tag goes
In the JSDoc comment directly above the class keyword. Several @implements tags can share one comment when a class satisfies more than one type.
The methods still need their own @param tags: @implements checks the class against the type, but it does not give the methods their parameter types. Without them, the parameters are implicitly any.
Gotchas
- The
implementskeyword is TypeScript syntax; in a.jsfile it is an error (TS8005). - A type written with
@typedef {object}and@propertylines can be implemented, but methods declared that way are function-typed properties; that is fine for@implements.
Questions
Can a JavaScript class implement a TypeScript interface?
Yes. Declare the interface in a .d.ts file, bring it in with @import, and put @implements {Store} on the class.
Sources
- JSDoc Reference: @implements · TypeScript handbook
- @implements · JSDoc
- Classes: implements clauses · TypeScript handbook
Last reviewed 20 October 2026.