TS6385Suggestion
Since TS 4.0Updated in TS 4.2

Fix TS6385: 'X' Is Deprecated

Learn why TypeScript reports TS6385 when a symbol carries a @deprecated JSDoc tag, why tsc never prints it, and how to migrate off the old API.

error TS6385: 'X' is deprecated

What This Error Means

TS6385 means the thing you just referenced has been marked obsolete by whoever wrote it. Somewhere in the declaration — in your own code or inside a library's .d.ts files — there is a /** @deprecated */ JSDoc tag, and TypeScript is relaying that note to you at every place the symbol is used.

Unlike almost every other code on this site, TS6385 is not a type error. It is a suggestion diagnostic, produced by the language service that powers your editor rather than by the compiler's checker. That has one consequence worth internalising before you start fixing anything: tsc never prints it. Your build is green, CI is green, tsc --noEmit exits zero — the message exists only in the editor, where it shows up as a strikethrough and a hover:

return event.keyCode === 13
//           ~~~~~~~ 'keyCode' is deprecated. ts(6385)
//           ^ rendered with a line through it in VS Code

The diagnostic is attached to the reference, not the declaration, so one deprecated helper can light up twenty files at once. TypeScript 4.0 introduced the @deprecated tag and this diagnostic together; 4.2 adjusted the wording to end with a period. A close relative, TS6387 (The signature '...' of 'X' is deprecated.), fires when you call a deprecated function — TS6385 is what you get for every other kind of reference, including the import specifier that brought the symbol in.

Common Causes

1. A Library API That Has Been Deprecated

The most common source by far, because the DOM and Node type definitions carry hundreds of @deprecated tags for legacy APIs. You did not do anything wrong — the platform moved on and the type definitions recorded it.

// ❌ Broken — with "lib": ["es2020", "dom"]
export function isSubmitShortcut(event: KeyboardEvent): boolean {
  return event.keyCode === 13 && event.metaKey
  //           ~~~~~~~ 'keyCode' is deprecated. ts(6385)
}
// ✅ Fixed — KeyboardEvent.key is the standardised replacement
export function isSubmitShortcut(event: KeyboardEvent): boolean {
  return event.key === "Enter" && event.metaKey
}

Hover the struck-through name before you reach for a search engine: the tag text is shown in the tooltip and almost always names what to use instead.

2. Your Own Deprecated Export, Still Referenced

You marked an internal helper for removal and left the tag in place, which is exactly right — but every call site is now annotated, including the ones you have not migrated yet.

// orders/legacy.ts
export interface Order {
  id: string
  total: number
}
 
/** @deprecated Use fetchOrdersPage — this loads every order in one request. */
export async function fetchOrders(): Promise<Order[]> {
  return []
}
 
export async function fetchOrdersPage(page: number): Promise<Order[]> {
  return [{ id: String(page), total: 0 }]
}
// ❌ Broken — dashboard.ts
import { fetchOrders } from "./orders/legacy"
//       ~~~~~~~~~~~ 'fetchOrders' is deprecated. ts(6385)
 
export const orderLoader = fetchOrders
//                         ~~~~~~~~~~~ 'fetchOrders' is deprecated. ts(6385)
// ✅ Fixed — migrate to the replacement the tag names
import { fetchOrdersPage } from "./orders/legacy"
 
export const orderLoader = () => fetchOrdersPage(1)

Note that the import specifier is flagged too. That is useful: a file with a struck-through import has at least one migration left in it, so the import list doubles as a to-do list.

3. A Deprecated Type or Interface in an Annotation

Types get the same treatment as values. Referencing a deprecated interface or type alias in an annotation, a generic argument or an extends clause reports TS6385 at the reference.

// ❌ Broken
/** @deprecated Use ShippingAddress — PostalAddress has no country field. */
export interface PostalAddress {
  street: string
  city: string
}
 
export interface Customer {
  name: string
  billingAddress: PostalAddress
  //              ~~~~~~~~~~~~~ 'PostalAddress' is deprecated. ts(6385)
}
// ✅ Fixed — point the annotation at the successor type
export interface ShippingAddress {
  street: string
  city: string
  country: string
}
 
export interface Customer {
  name: string
  billingAddress: ShippingAddress
}

4. A Deprecated Enum Member or Class Property

The tag works on individual members, not just whole declarations, which is how you retire one value from an enum or one field from a class without breaking the rest.

// ❌ Broken
export enum OrderStatus {
  Open = "open",
  Shipped = "shipped",
  Cancelled = "cancelled",
  /** @deprecated Use OrderStatus.Cancelled. */
  Voided = "voided",
}
 
export function isFinal(status: OrderStatus): boolean {
  return status === OrderStatus.Voided || status === OrderStatus.Shipped
  //                            ~~~~~~ 'Voided' is deprecated. ts(6385)
}
// ✅ Fixed — the member is gone once nothing references it
export enum OrderStatus {
  Open = "open",
  Shipped = "shipped",
  Cancelled = "cancelled",
}
 
export function isFinal(status: OrderStatus): boolean {
  return status === OrderStatus.Cancelled || status === OrderStatus.Shipped
}

How to Fix It

  1. Read the deprecation reason, then switch to the replacement. Hover the struck-through name — a well-written @deprecated tag says what to use instead, and following it is the only fix that actually removes the diagnostic. If the tag is bare, jump to the declaration with F12 and read the surrounding comments or the library's changelog.

  2. Migrate every reference, then delete the old symbol. Because the diagnostic sits on references, "Find All References" gives you the complete work list. Once the list is empty you can drop the deprecated declaration entirely — which is the point of the tag in the first place.

  3. Decide deliberately when you cannot migrate. Sometimes there is no replacement yet, or the deprecation is wrong: a few DefinitelyTyped packages carry stale @deprecated tags for APIs that are still current. TS6385 cannot break anything, so keeping the usage is a legitimate choice. Leave a short comment saying why, so the next reader does not re-open the question.

  4. Do not try to suppress it with // @ts-ignore. Suppression comments only apply to errors, and TS6385 is not one — the strikethrough stays. If the visual noise is the actual problem, turn off editor.showDeprecated in your editor settings rather than editing the source.

  5. Enforce it with ESLint if it needs to be enforced. No tsconfig.json option promotes TS6385 to a build failure. To make deprecated usage fail CI, enable @typescript-eslint/no-deprecated (it reads the same JSDoc tags through the type checker) and let the compiler keep doing type safety. And when you deprecate something of your own, always name the replacement in the tag — @deprecated Use fetchOrdersPage saves every future reader the archaeology.

FAQ

What causes TypeScript error TS6385?

A @deprecated JSDoc tag on the declaration you referenced. TypeScript resolves the identifier, finds the tag, and reports a suggestion at the reference site. Everything with a declaration can carry one: functions, const bindings, type aliases, interfaces, enum members, class members, and the import specifiers that pull them into a file. The tag may be yours or it may live in a dependency's type definitions — lib.dom.d.ts alone marks hundreds of legacy DOM APIs this way, which is why event.keyCode and window.orientation come up struck through in a project that never wrote a deprecation tag of its own.

Why is my code shown with a strikethrough in VS Code?

That is TS6385 being rendered. Your editor asks the TypeScript language service for suggestion diagnostics as you type, and any reference tagged reportsDeprecated gets the strikethrough treatment plus the hover text 'name' is deprecated. ts(6385). The hover is the useful part — it contains whatever the API author wrote after the tag, which is normally the name of the replacement. If you want the information without the styling, the VS Code setting editor.showDeprecated turns the strikethrough off while leaving the hover intact.

Can TS6385 fail my build?

No, and there is no setting that changes this. Suggestion diagnostics are produced by getSuggestionDiagnostics in the language service, which only editors call; the command-line compiler never emits them. Run tsc --noEmit on a file full of deprecated references and it prints nothing and exits zero. That is by design — deprecation is advice about the future, not a statement that the current code is unsound. If your team needs the advice to be binding, put it in the linter: @typescript-eslint/no-deprecated reports the same usages as a rule you can set to error, and that one does fail CI.

Related Errors

Practice This

Browse all TypeScript practice challenges to keep sharpening your type-level skills.

Share this reference

Become a TypeScript Pro

Track your progress through 200+ hands-on challenges. Free, sign in with GitHub.

Or start solving right away: explore all TypeScript challenges