Property 'x' does not exist on type 'y' (TS2339)
Filed under Next.js & React errors
The property is not part of the type TypeScript believes that value has — the type is missing it, the data was never typed, or the name is simply misspelled.
Fastest route
Give your AI this prompt
Copy it, replace the bracketed part with your error, and send it.
Preview the prompt
I am getting a TypeScript error: Property '[property]' does not exist on type '[type]' (TS2339). Here is the line of code that triggers it: [paste the line]. Here is the type definition involved: [paste the interface or type]. And here is what the data actually looks like when I log it: [paste a sample of the real data]. Please: 1) tell me whether this is a typo, an incomplete type, or data that was never typed, 2) fix it by correcting the code or the type so they match the real data I pasted, 3) if the property is only sometimes present, make it optional in the type and handle the missing case. Constraints: do not use "as any", @ts-ignore, or @ts-nocheck to silence this, do not loosen the TypeScript config, and make the smallest change that makes the type honest.
Fix it yourself
Follow the repair
- Read the error literally. "Property 'avatar' does not exist on type 'User'" tells you both halves of the problem. Open the
Usertype — hover over it in your editor, or jump to its definition — and read the properties it actually declares. Ifavataris not in the list, you have found the whole disagreement. - Rule out a typo or a wrong field name. Log the real data once and compare names character by character. Database rows and many APIs use snake_case (
created_at,user_id), while AI-written frontend code reflexively guesses camelCase. If the real name differs, fix the code — not the type — and expect a few more of these until every guessed name has met the real data. - Give untyped data a real type. The most common version of this error: the value came from a fetch and its type is an empty object or a generic placeholder. Write an interface that describes the response you actually receive, and apply it where the data enters:
Now every property oninterface Post { id: number; title: string; created_at: string; } const res = await fetch("/api/posts"); const posts: Post[] = await res.json();Postis legal, and misspelled ones get caught instantly. - Add the missing property to the type when the data genuinely has it. If the logged data really carries the field, the interface is simply incomplete — add the field with the right kind of value (
string,number, and so on). You are not cheating the checker; you are correcting the description it works from. - Match the type to values that are sometimes missing. If the property appears in some responses and not others, declare it optional —
avatar?: string— and let the code handle the missing case. TypeScript will then insist you check before using it, which is exactly the protection that prevents the "cannot read properties of undefined" crash at runtime. - Use casting only as a diagnostic, never as the fix.
(value as any).avatarmakes the red underline vanish by switching the proofreader off for that line — for real bugs as well as false alarms. The same goes for// @ts-ignorescattered through a file. If you use one to test a theory, delete it and write the real type before you move on. A codebase full ofanyhas quietly given up the one tool that catches shape bugs before your users do.
Why this happensOptional explanation
TypeScript is a proofreader that reads your code before it runs. Every value carries a type — a written description of what properties it has — and the proofreader rejects any code that reaches for a property the description does not mention. Crucially, it never runs your app and never sees your console log. If the description and the real data disagree, TypeScript trusts the description.
Disagreements creep in constantly in AI-built apps. A fetch returns data with no type attached, so the result gets described as an empty object and every property looks illegal. Or the type was written when the API returned five fields, and the API now returns six. Or the builder guessed a field name from the tutorial it was imitating. In all three cases the running app might work fine — plain JavaScript does not check any of this — but the build, which runs the checker, stops.
- The data was never typed: fetch results, JSON, and route params enter the app with a placeholder type that knows nothing.
- The type fell behind the data: the backend or API added or renamed a field and the interface was never updated.
- A simple typo:
createdAtin code,created_atin the real response — the checker cannot tell this from a missing feature. - The type collapsed to never: an empty or narrowed type where every property access is an error.
Quick answers
The property is right there in my console log. Why doesn't TypeScript believe me?
Because TypeScript checks types before the code runs, and it can only go by the type you declared — it never sees your console. If the declared type lacks the property, the build fails even when the runtime value has it. The fix is to make the type describe the real data.
Can I just turn off TypeScript checks or add // @ts-ignore?
Turning strictness down or sprinkling @ts-ignore across files hides this error along with the next real bug. A single ignore on one line, while you investigate, is a legitimate diagnostic step; making it the permanent fix means flying blind from then on.
What does it mean when the type is 'never'?
"Never" is TypeScript saying the value was narrowed down to nothing — usually a fetch result typed as an empty object, an error branch, or a variable whose type collapsed. It is the same missing-information problem: give the data a real type that includes the property, and check why the value narrowed to never.