How does TypeScript type inference work?
Quick answer
TypeScript fills in types you omit: literals get their literal or widened type, function return types are inferred from return statements, and generic arguments are inferred from the values you pass.
let count = 0 becomes number. const role = "admin" stays the literal "admin" because const cannot be reassigned. Contextual typing works the other way: a callback argument is inferred from the function you pass it to (arr.map(item => ...)).
Write types at module boundaries (function arguments, exported APIs, public class fields) and let inference handle locals. Over-annotating locals makes refactors noisy. When inference widens too far ([] is any[] without a hint), give the generic or a typed empty value ([] as User[] or User[] = []).