TypeScript error

TS2420: A class that does not match its @implements type

  • Error TS2420
  • Tested with TypeScript 5.9

The @implements tag asks TypeScript to check a class against a type: every member the type requires must exist on the class with a compatible type. TS2420 reports the class, and the lines under it name the missing or mismatched member.

It is the JSDoc form of class MemoryStore implements Store in a .ts file, and it is reported on the class even when nothing else uses it as a Store yet, which is the point of the tag.

At a glance

CodeTS2420
MessageClass '{0}' incorrectly implements interface '{1}'.
TypeScript's categoryerror
Listed underClasses, JSX and unused code
Turned on by No option: every checked file reports it
In .js files Reported when the file is checked: checkJs in jsconfig.json, or // @ts-check at the top of the file

The message is TypeScript's own text from its diagnostic messages file (Apache-2.0); {0} and {1} are filled in by tsc for each error.

What it looks like

store.js Error confirmed 5.9.3 TypeScript 5.9.3, run 21 October 2026: store.js(9,14): error TS2420: Class 'MemoryStore' incorrectly implements interface 'Store'. Property 'save' is missing in type 'MemoryStore' but required in type 'Store'. 6.0.3 TypeScript 6.0.3, run 21 October 2026: the same as 5.9.3. store.js(9,14): error TS2420: Class 'MemoryStore' incorrectly implements interface 'Store'. Property 'save' is missing in type 'MemoryStore' but required in type 'Store'. 7.0.2 TypeScript 7.0.2, run 21 October 2026: the same as 5.9.3. store.js(9,14): error TS2420: Class 'MemoryStore' incorrectly implements interface 'Store'. Property 'save' is missing in type 'MemoryStore' but required in type 'Store'. checked 21 October 2026
/**
 * @typedef {object} Store
 * @property {(id: string) => Promise<string | undefined>} load
 * @property {(id: string, value: string) => Promise<void>} save
 */

/** @implements {Store} */
export class MemoryStore {error TS2420: Class 'MemoryStore' incorrectly implements interface 'Store'.
  Property 'save' is missing in type 'MemoryStore' but required in type 'Store'.
  /** @type {Map<string, string>} */
  #items = new Map();

  /** @param {string} id */
  async load(id) {
    return this.#items.get(id);
  }
}
A class that does not have everything its @implements type requires.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": ["**/*.js"]
}

What causes it

  • A method of the type is missing from the class.
  • A member exists with an incompatible type (then TS2416 may appear on the member too).

How to fix it

Add the missing member

Implement every member the type lists, with compatible types.

store.js TypeScript 5.9.3 TypeScript 5.9.3, run 21 October 2026: No errors. 6.0.3 TypeScript 6.0.3, run 21 October 2026: the same as 5.9.3. No errors. 7.0.2 TypeScript 7.0.2, run 21 October 2026: the same as 5.9.3. No errors. checked 21 October 2026
/**
 * @typedef {object} Store
 * @property {(id: string) => Promise<string | undefined>} load
 * @property {(id: string, value: string) => Promise<void>} save
 */

/** @implements {Store} */
export class MemoryStore {
  /** @type {Map<string, string>} */
  #items = new Map();

  /** @param {string} id */
  async load(id) {
    return this.#items.get(id);
  }

  /**
   * @param {string} id
   * @param {string} value
   */
  async save(id, value) {
    this.#items.set(id, value);
  }
}
The class with every member of the type.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": ["**/*.js"]
}

Gotchas

  • @implements checks the class but does not type its methods' parameters: each still needs its own @param (TS7006 otherwise), as the recipe shows.

Sources

Last reviewed 21 October 2026.