TS2352Semantic Error
Since TS 1.0Updated in TS 4.0

Fix TS2352: Type Conversion May Be a Mistake

Learn why TypeScript throws TS2352 when a type assertion seems incorrect, and how to safely convert between types.

error TS2352: Conversion of type 'X' to type 'Y' may be a mistake

What This Error Means

TS2352 fires when you write a type assertion (as) between two types that TypeScript considers completely unrelated. TypeScript allows assertions between types that have some structural overlap, but when neither type extends the other and they share no common properties, TypeScript flags it as a likely mistake.

This is TypeScript protecting you from assertions that are almost certainly wrong. If you assert string as number, there's no runtime scenario where a string is actually a number — the assertion would just hide a bug.

// The general shape of the error:
// Conversion of type 'string' to type 'number' may be a mistake
// because neither type sufficiently overlaps with the other.

Common Causes

1. Asserting Between Unrelated Primitive Types

Trying to assert one primitive type as another when there's no relationship between them.

// ❌ Broken
const userInput = "42"
const count = userInput as number
//            ~~~~~~~~~~~~~~~~~~~~
// Error: Conversion of type 'string' to type 'number' may be a mistake
//        because neither type sufficiently overlaps with the other.
// ✅ Fixed — use a runtime conversion instead of an assertion
const userInput = "42"
const count = Number(userInput)

2. Asserting Between Incompatible Object Types

When two interfaces have no shared properties, TypeScript won't allow a direct assertion.

// ❌ Broken
interface ShippingAddress {
  street: string
  city: string
  zipCode: string
}
 
interface PaymentMethod {
  cardNumber: string
  expiryDate: string
  cvv: string
}
 
const address: ShippingAddress = { street: "123 Main", city: "NYC", zipCode: "10001" }
const payment = address as PaymentMethod
//              ~~~~~~~~~~~~~~~~~~~~~~~~
// Error: Conversion of type 'ShippingAddress' to type 'PaymentMethod'
//        may be a mistake because neither type sufficiently overlaps.
// ✅ Fixed — these are different types, map the data properly
const address: ShippingAddress = { street: "123 Main", city: "NYC", zipCode: "10001" }
const payment: PaymentMethod = {
  cardNumber: "4111111111111111",
  expiryDate: "12/28",
  cvv: "123",
}

3. Incorrect Assertion After Fetching Data

A common pattern is asserting API response data to a specific type when TypeScript sees the response as a different shape.

// ❌ Broken
interface UserProfile {
  id: number
  displayName: string
  avatarUrl: string
}
 
const response = await fetch("/api/profile")
const data: string = await response.text()
const profile = data as UserProfile
//              ~~~~~~~~~~~~~~~~~~~~~~
// Error: Conversion of type 'string' to type 'UserProfile' may be a mistake.
// ✅ Fixed — parse the JSON and validate the shape
interface UserProfile {
  id: number
  displayName: string
  avatarUrl: string
}
 
const response = await fetch("/api/profile")
const profile = (await response.json()) as UserProfile

How to Fix It

  1. Use runtime conversion functions. For primitives, use Number(), String(), Boolean(), or parseInt() instead of type assertions. These actually convert the value at runtime:

    const age = Number("25")     // actually converts to number
    const text = String(42)      // actually converts to string
  2. Fix the data flow. If the types genuinely don't overlap, you probably have a logic error. Check where the value comes from and ensure it's actually the type you need.

  3. Use the double assertion pattern when justified. If you've validated the data yourself and need to bypass TypeScript's overlap check:

    // Only use this when you've verified the data externally
    const config = rawData as unknown as AppConfig
  4. Add a type guard for runtime safety. Instead of blindly asserting, validate the shape of the data:

    function isUserProfile(data: unknown): data is UserProfile {
      return (
        typeof data === "object" &&
        data !== null &&
        "id" in data &&
        "displayName" in data
      )
    }
     
    const data = await response.json()
    if (isUserProfile(data)) {
      // TypeScript now knows data is UserProfile
      console.log(data.displayName)
    }
  5. Check if you need as at all. Many assertions are unnecessary. If the type is correct, TypeScript will infer it. If it's wrong, the assertion is hiding a bug.

FAQ

What causes TS2352?

TS2352 occurs when a type assertion uses as to convert between two types that have no structural overlap. TypeScript allows assertions when one type is a supertype or subtype of the other (e.g., unknown as string or HTMLElement as HTMLInputElement), but blocks assertions between completely unrelated types. This check prevents you from writing assertions that could never be correct at runtime.

How do I fix conversion may be a mistake?

First, ask whether you need a type assertion at all. If you're converting between primitive types, use a conversion function like Number() or String(). If you're working with API data, parse it with JSON.parse() or response.json() and then assert or validate. If you've already validated the data and need to override TypeScript, use a double assertion through unknown: value as unknown as TargetType.

When is double assertion acceptable?

Double assertion (value as unknown as Type) is a deliberate escape hatch. It's acceptable in a few scenarios: when writing test mocks where you need to satisfy a type without implementing every property, when working with external data you've already validated through a type guard, or when bridging gaps in third-party library types. It should always be accompanied by a comment explaining why it's safe. If you find yourself using it frequently, the underlying types probably need redesigning.

Related Errors

Share this reference

Stay Updated

Get the latest TypeScript tips, tutorials, and course updates delivered straight to your inbox.

No spam, unsubscribe at any time.