Short answer
Look at the type named in the message. If it is your own interface, add the property (optional with ? if it is not always there). If it is a union such as Cat | Dog, check which one you have first with 'meow' in pet or typeof before reading the property. If it is {} or never, the variable was typed from an empty initial value: give it a real type, such as useState<User | null>(null). For window.x or Express’s req.user, add the property with a global or module augmentation. Avoid casting to any, which hides real bugs.
Why TypeScript doesn’t know the property, and the fix
01
The property is missing from your type
The interface or type alias does not list the property, or the name is spelled differently from the data. Add it, as optional if the API does not always send it.
interface User { id: string; name: string; avatarUrl?: string; // optional: some users have none }02
A union type that has not been narrowed
“JavaScript has an operator for determining if an object or its prototype chain has a property with a name: the in operator.” TypeScript, Narrowing: the in operator
With a value typed as A | B, TypeScript only lets you read properties that both have. Check which one you have first, with the in operator, typeof, or a discriminant field, and TypeScript narrows the type inside that branch.
type Pet = { meow(): void } | { bark(): void }; function speak(pet: Pet) { if ('meow' in pet) pet.meow(); else pet.bark(); }03
The type was inferred from an empty value
const [user, setUser] = useState({}) makes user type {}, and useState([]) makes an array of never, so every property is unknown. Give the state or variable the type it will hold.
const [user, setUser] = useState<User | null>(null); const items: Product[] = [];04
A global or library type needs an extra property
“You can also add declarations to the global scope from inside a module” TypeScript, Declaration merging: global augmentation
window.dataLayer, a value your own middleware puts on Express’s req (req.user) or a custom field on a library type is not in that library’s types. Declare it once in a .d.ts file that your tsconfig includes, instead of casting at every use.
// types/global.d.ts export {}; declare global { interface Window { dataLayer: unknown[] } namespace Express { interface Request { user?: { id: string } } } }
Checked against the vendor’s docs on : TypeScript Handbook: Narrowing; TypeScript Handbook: Declaration merging (module and global augmentation).
Rather hand it over?
Fixed scope, fixed price, paid upfront. The work happens in writing; no call needed.
- from $450App Fix TicketOne reproducible bug in an existing mobile or web app, diagnosed and fixed.See scope and start
- from $450AI-Built App RescueA Lovable, Bolt or Cursor app checked end to end in 3 days, then its worst problems fixed at a fixed price.No issues worth fixing, no charge. If the Launch Check finds nothing rated medium or higher, Simon refunds the full $450. You keep the report either way. This applies to the first 10 Launch Checks bought after October 30, 2026.See scope and start
Related: “Cannot read properties of undefined” · TypeError: “x is not a function” · Next.js “window is not defined”